├── .babelrc ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── demo ├── debugging-grid.png ├── input.scss └── output.css ├── gulpfile.js ├── lib ├── core │ ├── functions.es6.js │ ├── functions.es6.js.map │ ├── index.js │ ├── index.js.map │ ├── variables.es6.js │ └── variables.es6.js.map ├── grid │ ├── fill-parent.es6.js │ ├── fill-parent.es6.js.map │ ├── index.js │ ├── index.js.map │ ├── omega.es6.js │ ├── omega.es6.js.map │ ├── outer-container.es6.js │ ├── outer-container.es6.js.map │ ├── pad.es6.js │ ├── pad.es6.js.map │ ├── row.es6.js │ ├── row.es6.js.map │ ├── shift.es6.js │ ├── shift.es6.js.map │ ├── show-grid.es6.js │ ├── show-grid.es6.js.map │ ├── span-columns.es6.js │ └── span-columns.es6.js.map ├── index.js ├── index.js.map ├── neat-parser.js └── neat-parser.js.map ├── package.json ├── src ├── core │ ├── functions.es6.js │ ├── index.js │ └── variables.es6.js ├── grid │ ├── fill-parent.es6.js │ ├── index.js │ ├── omega.es6.js │ ├── outer-container.es6.js │ ├── pad.es6.js │ ├── row.es6.js │ ├── shift.es6.js │ ├── show-grid.es6.js │ └── span-columns.es6.js ├── index.js └── neat-parser.js └── test └── test.es6.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015" 4 | ] 5 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-unused-expressions": [0], 4 | "no-underscore-dangle": [0], 5 | "no-reserved-keys": [2], 6 | "no-multi-spaces": [0], 7 | "no-extra-parens": [2], 8 | "no-unused-vars": [0], 9 | "no-loop-func": [0], 10 | "key-spacing": [0], 11 | "max-len": [2], 12 | "strict": [0], 13 | "indent": [ 14 | 2, 15 | 2 16 | ], 17 | "quotes": [ 18 | 2, 19 | "single", 20 | "avoid-escape" 21 | ], 22 | "curly": [0] 23 | }, 24 | "env": { 25 | "mocha": true, 26 | "node": true 27 | }, 28 | "parser": "babel-eslint" 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .idea/ 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | 3 | .idea/ 4 | node_modules/ 5 | 6 | test/ 7 | .travis.yml 8 | 9 | gulpfile.js 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "4.2" 5 | - "4.1" 6 | - "4.0" 7 | before_script: 8 | - npm install -g gulp 9 | script: gulp test 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2015 jo-asakura 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostCSS-Neat 2 | 3 | [![npm-version]][npm] [![travis-ci]][travis] 4 | 5 | ## A semantic and fluid grid framework on top of PostCSS 6 | 7 | [PostCSS-Neat][postcss-neat] is a fluid grid framework built with the aim of being easy enough to use out of the box and flexible enough to customize down the road. 8 | 9 | ## Using PostCSS-Neat 10 | 11 | Usage: 12 | 13 | ```js 14 | postcss([ 15 | require('postcss-neat')(/* { options } */) 16 | ]) 17 | ``` 18 | 19 | There is a gulp usage: 20 | 21 | ```js 22 | var gulp = require('gulp'); 23 | gulp 24 | .task('css', function () { 25 | var processors = [ 26 | require('autoprefixer-core')({ browsers: ['last 1 version'] }), 27 | require('postcss-neat')(/* { options } */) 28 | ]; 29 | return gulp.src('./input/*.css') 30 | .pipe(require('gulp-postcss')(processors)) 31 | .pipe(gulp.dest('./output/')); 32 | }) 33 | .task('default', ['css']); 34 | ``` 35 | 36 | See the [demo page](http://jo-asakura.github.io/postcss-neat/demo.html) for a full list of features. 37 | 38 | Let's walk through a simple example. Include the `outer-container` at-rule in the topmost container (to which the `max-width` setting will be applied): 39 | 40 | ```css 41 | .container { 42 | @neat-outer-container; 43 | } 44 | ``` 45 | 46 | Then use `span-columns` on any element to specify the number of columns it should span: 47 | 48 | ```css 49 | .element { 50 | @neat-span-columns 6; 51 | } 52 | ``` 53 | 54 | If the element's parent isn't the top-most container, you need to add the number of columns of the parent element to keep the right proportions: 55 | 56 | ```css 57 | .container { 58 | @neat-outer-container; 59 | 60 | .parent-element { 61 | @neat-span-columns 8; 62 | 63 | .element { 64 | @neat-span-columns 6 8; 65 | } 66 | } 67 | } 68 | ``` 69 | 70 | To make your layout responsive, use the [postcss-media-minmax](https://github.com/postcss/postcss-media-minmax) media queries functionality to modify both the grid and the layout: 71 | 72 | ```css 73 | .container { 74 | @neat-span-columns 4; 75 | 76 | @media (width >= 768px) { 77 | @neat-span-columns 2; 78 | } 79 | } 80 | ``` 81 | 82 | To help debug your layouts there is a `show-grid` at-rule, note that it should be used in conjunction with `outer-container`: 83 | 84 | ```css 85 | .container { 86 | @neat-outer-container; 87 | @neat-show-grid; /* defaults to 1 12 */ 88 | } 89 | ``` 90 | 91 | The result you get by using `show-grid` at-rule is shown below: 92 | @neat-show-grid 93 | 94 | The third parameter of `show-grid` at-rule controls the location of where the grid will be applied to. The allowed values are `before`, `after` (default value) or `background`: 95 | 96 | ```css 97 | .container { 98 | @neat-outer-container; 99 | @neat-show-grid 4 12 background; 100 | } 101 | ``` 102 | 103 | ### Custom settings 104 | 105 | If you are planning to override the default grid settings (12 columns, and etc.), set variables you want to override in `options` that you pass to PostCSS-neat call: 106 | 107 | ```js 108 | postcss([ 109 | require('postcss-neat')({ 110 | neatMaxWidth: '128em' 111 | }) 112 | ]) 113 | ``` 114 | 115 | There is a list of all available variables: 116 | 117 | - `neatDefaultDisplay`, sets the default display mode. Can be `block`, `table` or `block-collapse`. Default is `block`. 118 | - `neatDefaultDirection`, sets the default layout direction of the grid. Can be `LTR` or `RTL`. Default is `LTR`. 119 | - `neatGridColumns`, sets the total number of columns in the grid. Default is `12`. 120 | - `neatColumnWidth`, sets the relative width of a single grid column. Default is `4.235801032000001em`. 121 | - `neatGutterWidth`, sets the relative width of a single grid gutter. Default is `1.618em`. 122 | - `neatMaxWidth`, sets the max-width property of the element that includes `outer-container`. Default is `64em`. 123 | - `debugGridColor`, sets the background color for the debugging grid. Default is `#ecf0f1`. 124 | - `debugGridLocation`, sets the default location of the debugging grid. Default is `after`. 125 | 126 | ## PostCSS-Neat v1 127 | 128 | Second version of PostCSS-Neat introduced breaking changes. [Here][old-doc] is old documentation if you're still using PostCSS-Neat version 1.X.X. 129 | 130 | ## Credits 131 | 132 | PostCSS-Neat is created and maintained by Alexandr Marinenko. The project is heavily inspired by amazing Sass framework [Bourbon Neat](http://neat.bourbon.io). Tweet your questions or suggestions to [@jo_asakura](https://twitter.com/jo_asakura). 133 | 134 | ## License 135 | 136 | Copyright © 2015 Alexandr Marinenko. PostCSS-Neat is free software, and may be redistributed under the terms specified in the [license](LICENSE). 137 | 138 | 139 | [npm]: https://www.npmjs.com/package/postcss-neat 140 | [npm-version]: http://img.shields.io/npm/v/postcss-neat.svg?style=flat-square 141 | 142 | [travis]: https://travis-ci.org/jo-asakura/postcss-neat 143 | [travis-ci]: https://img.shields.io/travis/jo-asakura/postcss-neat/master.svg?style=flat-square 144 | 145 | [postcss-neat]: http://jo-asakura.github.io/postcss-neat/ 146 | [old-doc]: https://github.com/jo-asakura/postcss-neat/blob/0197c392253b13196e00145f6365b330024a1a5f/README.md 147 | -------------------------------------------------------------------------------- /demo/debugging-grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo-asakura/postcss-neat/aba997b5a5e14c447be189b975233a04e849a000/demo/debugging-grid.png -------------------------------------------------------------------------------- /demo/input.scss: -------------------------------------------------------------------------------- 1 | $minWidth: 315px; 2 | 3 | /* greens */ 4 | $colorTurquoise: #1abc9c; 5 | $colorGreenSea: #16a085; 6 | 7 | /* blues */ 8 | $colorPeterRiver: #3498db; 9 | $colorBelizeHole: #2980b9; 10 | 11 | /* violets */ 12 | $colorAmethyst: #9b59b6; 13 | $colorWisteria: #8e44ad; 14 | 15 | /* blacks / dark blues */ 16 | $colorWetAsphalt: #34495e; 17 | $colorMidnightBlue: #2c3e50; 18 | 19 | /* yellows */ 20 | $colorSunFlower: #f1c40f; 21 | $colorOrange: #f39c12; 22 | 23 | /* oranges */ 24 | $colorCarrot: #e67e22; 25 | $colorPumpkin: #d35400; 26 | 27 | /* reds */ 28 | $colorAlizarin: #e74c3c; 29 | $colorPomegranate: #c0392b; 30 | 31 | /* whites */ 32 | $colorClouds: #ecf0f1; 33 | $colorSilver: #bdc3c7; 34 | $colorWhite: #fefefe; 35 | 36 | /* grays */ 37 | $colorConcrete: #95a5a6; 38 | $colorAsbestos: #7f8c8d; 39 | 40 | /* -- */ 41 | 42 | *, 43 | *:before, 44 | *:after { 45 | box-sizing: border-box; 46 | } 47 | 48 | html, 49 | body { 50 | background: $colorWhite; 51 | color: $colorWhite; 52 | font: normal 16px/1em 'Lato'; 53 | margin: 0; 54 | min-width: $minWidth; 55 | padding: 0; 56 | } 57 | 58 | .u-text-center { 59 | text-align: center; 60 | } 61 | 62 | .u-light-bg { 63 | background: $colorTurquoise; 64 | } 65 | 66 | .u-dark-bg { 67 | background: #17a689; 68 | } 69 | 70 | .u-alt-bg { 71 | background: #148f77; 72 | } 73 | 74 | .u-block { 75 | min-height: 80px; 76 | line-height: 1.25em; 77 | padding: 10px; 78 | } 79 | 80 | @media only screen and (min-width: 331px) and (max-width: 500px) { 81 | .u-block { 82 | font-size: .85em; 83 | padding: 5px; 84 | word-wrap: break-word; 85 | } 86 | } 87 | 88 | @media only screen and (max-width: 330px) { 89 | .u-block { 90 | font-size: 0; 91 | padding: 0; 92 | } 93 | } 94 | 95 | .u-buffer-bottom { 96 | padding-bottom: 20px; 97 | } 98 | 99 | .outer-container { 100 | @neat-outer-container; 101 | } 102 | 103 | header, 104 | footer { 105 | background: $colorTurquoise; 106 | padding: 20px; 107 | width: 100%; 108 | 109 | h1 { 110 | cursor: default; 111 | font-size: 1.5em; 112 | font-weight: normal; 113 | line-height: 1.25em; 114 | margin: 0; 115 | padding: 0; 116 | } 117 | } 118 | 119 | .global-wrapper { 120 | @neat-outer-container; 121 | @neat-show-grid; /* defaults to 1 12 */ 122 | padding-bottom: 40px; 123 | position: relative; 124 | } 125 | 126 | .section-block { 127 | position: relative; 128 | z-index: 1; 129 | } 130 | 131 | .outer-container__heading { 132 | color: $colorWetAsphalt; 133 | cursor: default; 134 | font-size: 1.15em; 135 | font-weight: bold; 136 | margin: 0; 137 | padding: 40px 0 20px; 138 | } 139 | 140 | .outer-container__top-label { 141 | font-size: 1.05em; 142 | padding-bottom: 20px; 143 | } 144 | 145 | /* -- */ 146 | .basic__outer { 147 | @neat-outer-container; 148 | padding: 20px 0; 149 | } 150 | 151 | .basic__outer__col { 152 | @neat-span-columns 6; 153 | } 154 | 155 | /* -- */ 156 | .multiple-rows__outer { 157 | @neat-outer-container; 158 | padding: 20px 0 0; 159 | 160 | .u-block { 161 | margin-bottom: 20px; 162 | } 163 | } 164 | 165 | .multiple-rows__1 { 166 | @neat-span-columns 1; 167 | } 168 | 169 | .multiple-rows__11 { 170 | @neat-span-columns 11; 171 | @neat-omega; 172 | } 173 | 174 | .multiple-rows__2 { 175 | @neat-span-columns 2; 176 | } 177 | 178 | .multiple-rows__10 { 179 | @neat-span-columns 10; 180 | @neat-omega; 181 | } 182 | 183 | .multiple-rows__3 { 184 | @neat-span-columns 3; 185 | } 186 | 187 | .multiple-rows__9 { 188 | @neat-span-columns 9; 189 | @neat-omega; 190 | } 191 | 192 | .multiple-rows__4 { 193 | @neat-span-columns 4; 194 | } 195 | 196 | .multiple-rows__8 { 197 | @neat-span-columns 8; 198 | @neat-omega; 199 | } 200 | 201 | .multiple-rows__5 { 202 | @neat-span-columns 5; 203 | } 204 | 205 | .multiple-rows__7 { 206 | @neat-span-columns 7; 207 | @neat-omega; 208 | } 209 | 210 | .multiple-rows__6 { 211 | @neat-span-columns 6; 212 | } 213 | 214 | /* -- */ 215 | .nesting-columns__outer { 216 | @neat-outer-container; 217 | padding: 20px 0; 218 | } 219 | 220 | .nesting-columns__4 { 221 | @neat-span-columns 4; 222 | } 223 | 224 | .nesting-columns__8 { 225 | @neat-span-columns 8; 226 | padding-bottom: 0; 227 | padding-left: 0; 228 | padding-right: 0; 229 | } 230 | 231 | .multiple-rows__48 { 232 | @neat-span-columns 4 8; 233 | } 234 | 235 | /* -- */ 236 | .table__outer { 237 | @neat-outer-container; 238 | padding: 20px 0 0; 239 | } 240 | 241 | .table__row { 242 | @neat-fill-parent; 243 | @neat-row table; 244 | } 245 | 246 | .table__cell--4 { 247 | @neat-span-columns 4 12 table; 248 | @neat-pad; 249 | 250 | /* just a visual thing */ 251 | border-right: 1px solid #17a689; 252 | } 253 | 254 | /* this is also visual thing */ 255 | @media only screen and (max-width: 330px) { 256 | .table__cell--4 { 257 | padding-bottom: 40px; 258 | } 259 | } 260 | 261 | .table__cell--8 { 262 | @neat-span-columns 8 12 table; 263 | @neat-pad; 264 | } 265 | 266 | /* -- */ 267 | .shift__outer { 268 | @neat-outer-container; 269 | padding: 20px 0; 270 | } 271 | 272 | .shift__nested { 273 | @neat-span-columns 6; 274 | @neat-shift 3; 275 | } 276 | 277 | /* -- */ 278 | .auto-rows__outer { 279 | padding: 20px 0 0; 280 | } 281 | 282 | .auto-rows__list { 283 | @neat-outer-container; 284 | } 285 | 286 | .auto-rows__list__item { 287 | @neat-span-columns 3; 288 | @neat-omega 4n; 289 | margin-bottom: 20px; 290 | min-height: 140px; 291 | } 292 | 293 | /* -- */ 294 | .mixed__outer { 295 | @neat-outer-container; 296 | padding: 20px 0; 297 | } 298 | 299 | .mixed__list { 300 | @neat-outer-container; 301 | } 302 | 303 | .mixed__list__item { 304 | @neat-span-columns 3; 305 | @neat-omega 3n; 306 | margin-bottom: 20px; 307 | min-height: 180px; 308 | 309 | &:nth-child(4) { 310 | @neat-shift 3; 311 | } 312 | } 313 | 314 | /* -- */ 315 | .media__outer { 316 | @neat-outer-container; 317 | padding: 20px 0; 318 | } 319 | 320 | .media__4 { 321 | @neat-span-columns 4; 322 | } 323 | 324 | @media (max-width: 500px) { 325 | .media__4 { 326 | @neat-span-columns 6; 327 | } 328 | } 329 | 330 | .media__8 { 331 | @neat-span-columns 8; 332 | } 333 | 334 | @media (max-width: 500px) { 335 | .media__8 { 336 | @neat-span-columns 6; 337 | } 338 | } -------------------------------------------------------------------------------- /demo/output.css: -------------------------------------------------------------------------------- 1 | /* greens */ 2 | 3 | /* blues */ 4 | 5 | /* violets */ 6 | 7 | /* blacks / dark blues */ 8 | 9 | /* yellows */ 10 | 11 | /* oranges */ 12 | 13 | /* reds */ 14 | 15 | /* whites */ 16 | 17 | /* grays */ 18 | 19 | /* -- */ 20 | 21 | *, 22 | *:before, 23 | *:after { 24 | box-sizing: border-box; 25 | } 26 | 27 | html, 28 | body { 29 | background: #fefefe; 30 | color: #fefefe; 31 | font: normal 16px/1em 'Lato'; 32 | margin: 0; 33 | min-width: 315px; 34 | padding: 0; 35 | } 36 | 37 | .u-text-center { 38 | text-align: center; 39 | } 40 | 41 | .u-light-bg { 42 | background: #1abc9c; 43 | } 44 | 45 | .u-dark-bg { 46 | background: #17a689; 47 | } 48 | 49 | .u-alt-bg { 50 | background: #148f77; 51 | } 52 | 53 | .u-block { 54 | min-height: 80px; 55 | line-height: 1.25em; 56 | padding: 10px; 57 | } 58 | 59 | @media only screen and (min-width: 331px) and (max-width: 500px) { 60 | .u-block { 61 | font-size: .85em; 62 | padding: 5px; 63 | word-wrap: break-word; 64 | } 65 | } 66 | 67 | @media only screen and (max-width: 330px) { 68 | .u-block { 69 | font-size: 0; 70 | padding: 0; 71 | } 72 | } 73 | 74 | .u-buffer-bottom { 75 | padding-bottom: 20px; 76 | } 77 | 78 | .outer-container { 79 | max-width: 64em; 80 | margin-left: auto; 81 | margin-right: auto; 82 | *zoom: 1; 83 | } 84 | 85 | .outer-container:before, .outer-container:after { 86 | content: " "; 87 | display: table; 88 | } 89 | 90 | .outer-container:after { 91 | clear: both; 92 | } 93 | 94 | header, 95 | footer { 96 | background: #1abc9c; 97 | padding: 20px; 98 | width: 100%; 99 | } 100 | 101 | header h1, footer h1 { 102 | cursor: default; 103 | font-size: 1.5em; 104 | font-weight: normal; 105 | line-height: 1.25em; 106 | margin: 0; 107 | padding: 0; 108 | } 109 | 110 | .global-wrapper { 111 | max-width: 64em; 112 | margin-left: auto; 113 | margin-right: auto; 114 | *zoom: 1; /* defaults to 1 12 */ 115 | padding-bottom: 40px; 116 | position: relative; 117 | } 118 | 119 | .global-wrapper:before, .global-wrapper:after { 120 | content: " "; 121 | display: table; 122 | } 123 | 124 | .global-wrapper:after { 125 | clear: both; 126 | } 127 | 128 | .global-wrapper:after { 129 | background: linear-gradient(to right,#ecf0f1 0.00000000%, #ecf0f1 6.17215270%,transparent 6.17215270%, transparent 8.52980430%,#ecf0f1 8.52980430%, #ecf0f1 14.70195700%,transparent 14.70195700%, transparent 17.05960860%,#ecf0f1 17.05960860%, #ecf0f1 23.23176130%,transparent 23.23176130%, transparent 25.58941290%,#ecf0f1 25.58941290%, #ecf0f1 31.76156560%,transparent 31.76156560%, transparent 34.11921720%,#ecf0f1 34.11921720%, #ecf0f1 40.29136990%,transparent 40.29136990%, transparent 42.64902150%,#ecf0f1 42.64902150%, #ecf0f1 48.82117420%,transparent 48.82117420%, transparent 51.17882580%,#ecf0f1 51.17882580%, #ecf0f1 57.35097850%,transparent 57.35097850%, transparent 59.70863010%,#ecf0f1 59.70863010%, #ecf0f1 65.88078280%,transparent 65.88078280%, transparent 68.23843440%,#ecf0f1 68.23843440%, #ecf0f1 74.41058710%,transparent 74.41058710%, transparent 76.76823870%,#ecf0f1 76.76823870%, #ecf0f1 82.94039140%,transparent 82.94039140%, transparent 85.29804300%,#ecf0f1 85.29804300%, #ecf0f1 91.47019570%,transparent 91.47019570%, transparent 93.82784730%,#ecf0f1 93.82784730%, #ecf0f1 100.00000000%); 130 | bottom: 0; 131 | display: block; 132 | left: 0; 133 | position: absolute; 134 | right: 0; 135 | top: 0; 136 | } 137 | 138 | .section-block { 139 | position: relative; 140 | z-index: 1; 141 | } 142 | 143 | .outer-container__heading { 144 | color: #34495e; 145 | cursor: default; 146 | font-size: 1.15em; 147 | font-weight: bold; 148 | margin: 0; 149 | padding: 40px 0 20px; 150 | } 151 | 152 | .outer-container__top-label { 153 | font-size: 1.05em; 154 | padding-bottom: 20px; 155 | } 156 | 157 | /* -- */ 158 | .basic__outer { 159 | max-width: 64em; 160 | margin-left: auto; 161 | margin-right: auto; 162 | *zoom: 1; 163 | padding: 20px 0; 164 | } 165 | .basic__outer:before, .basic__outer:after { 166 | content: " "; 167 | display: table; 168 | } 169 | .basic__outer:after { 170 | clear: both; 171 | } 172 | 173 | .basic__outer__col { 174 | display: block; 175 | float: left; 176 | margin-right: 2.35765160%; 177 | width: 48.82117420%; 178 | } 179 | 180 | .basic__outer__col:last-child { 181 | margin-right: 0; 182 | } 183 | 184 | /* -- */ 185 | .multiple-rows__outer { 186 | max-width: 64em; 187 | margin-left: auto; 188 | margin-right: auto; 189 | *zoom: 1; 190 | padding: 20px 0 0; 191 | } 192 | .multiple-rows__outer .u-block { 193 | margin-bottom: 20px; 194 | } 195 | .multiple-rows__outer:before, .multiple-rows__outer:after { 196 | content: " "; 197 | display: table; 198 | } 199 | .multiple-rows__outer:after { 200 | clear: both; 201 | } 202 | 203 | .multiple-rows__1 { 204 | display: block; 205 | float: left; 206 | margin-right: 2.35765160%; 207 | width: 6.17215270%; 208 | } 209 | 210 | .multiple-rows__1:last-child { 211 | margin-right: 0; 212 | } 213 | 214 | .multiple-rows__11 { 215 | display: block; 216 | float: left; 217 | margin-right: 2.35765160%; 218 | width: 91.47019570%; 219 | margin-right: 0; 220 | } 221 | 222 | .multiple-rows__11:last-child { 223 | margin-right: 0; 224 | } 225 | 226 | .multiple-rows__2 { 227 | display: block; 228 | float: left; 229 | margin-right: 2.35765160%; 230 | width: 14.70195700%; 231 | } 232 | 233 | .multiple-rows__2:last-child { 234 | margin-right: 0; 235 | } 236 | 237 | .multiple-rows__10 { 238 | display: block; 239 | float: left; 240 | margin-right: 2.35765160%; 241 | width: 82.94039140%; 242 | margin-right: 0; 243 | } 244 | 245 | .multiple-rows__10:last-child { 246 | margin-right: 0; 247 | } 248 | 249 | .multiple-rows__3 { 250 | display: block; 251 | float: left; 252 | margin-right: 2.35765160%; 253 | width: 23.23176130%; 254 | } 255 | 256 | .multiple-rows__3:last-child { 257 | margin-right: 0; 258 | } 259 | 260 | .multiple-rows__9 { 261 | display: block; 262 | float: left; 263 | margin-right: 2.35765160%; 264 | width: 74.41058710%; 265 | margin-right: 0; 266 | } 267 | 268 | .multiple-rows__9:last-child { 269 | margin-right: 0; 270 | } 271 | 272 | .multiple-rows__4 { 273 | display: block; 274 | float: left; 275 | margin-right: 2.35765160%; 276 | width: 31.76156560%; 277 | } 278 | 279 | .multiple-rows__4:last-child { 280 | margin-right: 0; 281 | } 282 | 283 | .multiple-rows__8 { 284 | display: block; 285 | float: left; 286 | margin-right: 2.35765160%; 287 | width: 65.88078280%; 288 | margin-right: 0; 289 | } 290 | 291 | .multiple-rows__8:last-child { 292 | margin-right: 0; 293 | } 294 | 295 | .multiple-rows__5 { 296 | display: block; 297 | float: left; 298 | margin-right: 2.35765160%; 299 | width: 40.29136990%; 300 | } 301 | 302 | .multiple-rows__5:last-child { 303 | margin-right: 0; 304 | } 305 | 306 | .multiple-rows__7 { 307 | display: block; 308 | float: left; 309 | margin-right: 2.35765160%; 310 | width: 57.35097850%; 311 | margin-right: 0; 312 | } 313 | 314 | .multiple-rows__7:last-child { 315 | margin-right: 0; 316 | } 317 | 318 | .multiple-rows__6 { 319 | display: block; 320 | float: left; 321 | margin-right: 2.35765160%; 322 | width: 48.82117420%; 323 | } 324 | 325 | .multiple-rows__6:last-child { 326 | margin-right: 0; 327 | } 328 | 329 | /* -- */ 330 | .nesting-columns__outer { 331 | max-width: 64em; 332 | margin-left: auto; 333 | margin-right: auto; 334 | *zoom: 1; 335 | padding: 20px 0; 336 | } 337 | .nesting-columns__outer:before, .nesting-columns__outer:after { 338 | content: " "; 339 | display: table; 340 | } 341 | .nesting-columns__outer:after { 342 | clear: both; 343 | } 344 | 345 | .nesting-columns__4 { 346 | display: block; 347 | float: left; 348 | margin-right: 2.35765160%; 349 | width: 31.76156560%; 350 | } 351 | 352 | .nesting-columns__4:last-child { 353 | margin-right: 0; 354 | } 355 | 356 | .nesting-columns__8 { 357 | display: block; 358 | float: left; 359 | margin-right: 2.35765160%; 360 | width: 65.88078280%; 361 | padding-bottom: 0; 362 | padding-left: 0; 363 | padding-right: 0; 364 | } 365 | 366 | .nesting-columns__8:last-child { 367 | margin-right: 0; 368 | } 369 | 370 | .multiple-rows__48 { 371 | display: block; 372 | float: left; 373 | margin-right: 3.57866361%; 374 | width: 48.21066820%; 375 | } 376 | 377 | .multiple-rows__48:last-child { 378 | margin-right: 0; 379 | } 380 | 381 | /* -- */ 382 | .table__outer { 383 | max-width: 64em; 384 | margin-left: auto; 385 | margin-right: auto; 386 | *zoom: 1; 387 | padding: 20px 0 0; 388 | } 389 | .table__outer:before, .table__outer:after { 390 | content: " "; 391 | display: table; 392 | } 393 | .table__outer:after { 394 | clear: both; 395 | } 396 | 397 | .table__row { 398 | box-sizing: border-box; 399 | width: 100%; 400 | display: table; 401 | table-layout: fixed; 402 | box-sizing: border-box; 403 | width: 100%; 404 | } 405 | 406 | .table__cell--4 { 407 | display: table-cell; 408 | width: 33.33333333%; 409 | padding: 2.35765160%; 410 | 411 | /* just a visual thing */ 412 | border-right: 1px solid #17a689; 413 | } 414 | 415 | /* this is also visual thing */ 416 | @media only screen and (max-width: 330px) { 417 | .table__cell--4 { 418 | padding-bottom: 40px; 419 | } 420 | } 421 | 422 | .table__cell--8 { 423 | display: table-cell; 424 | width: 66.66666667%; 425 | padding: 2.35765160%; 426 | } 427 | 428 | /* -- */ 429 | .shift__outer { 430 | max-width: 64em; 431 | margin-left: auto; 432 | margin-right: auto; 433 | *zoom: 1; 434 | padding: 20px 0; 435 | } 436 | .shift__outer:before, .shift__outer:after { 437 | content: " "; 438 | display: table; 439 | } 440 | .shift__outer:after { 441 | clear: both; 442 | } 443 | 444 | .shift__nested { 445 | display: block; 446 | float: left; 447 | margin-right: 2.35765160%; 448 | width: 48.82117420%; 449 | margin-left: 25.58941290%; 450 | } 451 | 452 | .shift__nested:last-child { 453 | margin-right: 0; 454 | } 455 | 456 | /* -- */ 457 | .auto-rows__outer { 458 | padding: 20px 0 0; 459 | } 460 | 461 | .auto-rows__list { 462 | max-width: 64em; 463 | margin-left: auto; 464 | margin-right: auto; 465 | *zoom: 1; 466 | } 467 | 468 | .auto-rows__list:before, .auto-rows__list:after { 469 | content: " "; 470 | display: table; 471 | } 472 | 473 | .auto-rows__list:after { 474 | clear: both; 475 | } 476 | 477 | .auto-rows__list__item { 478 | display: block; 479 | float: left; 480 | margin-right: 2.35765160%; 481 | width: 23.23176130%; 482 | margin-bottom: 20px; 483 | min-height: 140px; 484 | } 485 | 486 | .auto-rows__list__item:last-child { 487 | margin-right: 0; 488 | } 489 | 490 | .auto-rows__list__item:nth-child(4n) { 491 | margin-right: 0; 492 | } 493 | 494 | .auto-rows__list__item:nth-child(4n + 1) { 495 | clear: left; 496 | } 497 | 498 | /* -- */ 499 | .mixed__outer { 500 | max-width: 64em; 501 | margin-left: auto; 502 | margin-right: auto; 503 | *zoom: 1; 504 | padding: 20px 0; 505 | } 506 | .mixed__outer:before, .mixed__outer:after { 507 | content: " "; 508 | display: table; 509 | } 510 | .mixed__outer:after { 511 | clear: both; 512 | } 513 | 514 | .mixed__list { 515 | max-width: 64em; 516 | margin-left: auto; 517 | margin-right: auto; 518 | *zoom: 1; 519 | } 520 | 521 | .mixed__list:before, .mixed__list:after { 522 | content: " "; 523 | display: table; 524 | } 525 | 526 | .mixed__list:after { 527 | clear: both; 528 | } 529 | 530 | .mixed__list__item { 531 | display: block; 532 | float: left; 533 | margin-right: 2.35765160%; 534 | width: 23.23176130%; 535 | margin-bottom: 20px; 536 | min-height: 180px; 537 | } 538 | 539 | .mixed__list__item:nth-child(4) { 540 | margin-left: 25.58941290%; 541 | } 542 | 543 | .mixed__list__item:last-child { 544 | margin-right: 0; 545 | } 546 | 547 | .mixed__list__item:nth-child(3n) { 548 | margin-right: 0; 549 | } 550 | 551 | .mixed__list__item:nth-child(3n + 1) { 552 | clear: left; 553 | } 554 | 555 | /* -- */ 556 | .media__outer { 557 | max-width: 64em; 558 | margin-left: auto; 559 | margin-right: auto; 560 | *zoom: 1; 561 | padding: 20px 0; 562 | } 563 | .media__outer:before, .media__outer:after { 564 | content: " "; 565 | display: table; 566 | } 567 | .media__outer:after { 568 | clear: both; 569 | } 570 | 571 | .media__4 { 572 | display: block; 573 | float: left; 574 | margin-right: 2.35765160%; 575 | width: 31.76156560%; 576 | } 577 | 578 | .media__4:last-child { 579 | margin-right: 0; 580 | } 581 | 582 | @media (max-width: 500px) { 583 | .media__4 { 584 | display: block; 585 | float: left; 586 | margin-right: 2.35765160%; 587 | width: 48.82117420%; 588 | } 589 | .media__4:last-child { 590 | margin-right: 0; 591 | } 592 | } 593 | 594 | .media__8 { 595 | display: block; 596 | float: left; 597 | margin-right: 2.35765160%; 598 | width: 65.88078280%; 599 | } 600 | 601 | .media__8:last-child { 602 | margin-right: 0; 603 | } 604 | 605 | @media (max-width: 500px) { 606 | .media__8 { 607 | display: block; 608 | float: left; 609 | margin-right: 2.35765160%; 610 | width: 48.82117420%; 611 | } 612 | .media__8:last-child { 613 | margin-right: 0; 614 | } 615 | } -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('babel-core/register'); 4 | var gulp = require('gulp'); 5 | 6 | gulp.task('lint', function () { 7 | var eslint = require('gulp-eslint'); 8 | return gulp.src(['src/index.js', 'test/*.js', 'gulpfile.js']) 9 | .pipe(eslint()) 10 | .pipe(eslint.format()) 11 | .pipe(eslint.failAfterError()); 12 | }); 13 | 14 | gulp.task('clean', function (cb) { 15 | var del = require('del'); 16 | del(['lib'], cb); 17 | }); 18 | 19 | gulp.task('build', ['lint', 'clean'], function () { 20 | var babel = require('gulp-babel'); 21 | var sourcemaps = require('gulp-sourcemaps'); 22 | 23 | return gulp.src('src/**/*.js') 24 | .pipe(sourcemaps.init()) 25 | .pipe(babel({ presets: ['es2015'] })) 26 | .pipe(sourcemaps.write('.')) 27 | .pipe(gulp.dest('lib')); 28 | }); 29 | 30 | gulp.task('test', function () { 31 | var mocha = require('gulp-mocha'); 32 | return gulp.src('test/*.js', { read: false }).pipe(mocha()); 33 | }); 34 | 35 | // an example of usage (see /demo folder for the result) 36 | gulp.task('css', function () { 37 | var concat = require('gulp-concat'); 38 | var postcss = require('gulp-postcss'); 39 | var postcssNeat = require('./lib/index.js'); 40 | var postcssNested = require('postcss-nested'); 41 | var postcssVars = require('postcss-simple-vars'); 42 | var postcssMinMax = require('postcss-media-minmax'); 43 | var autoprefixer = require('autoprefixer'); 44 | 45 | var processors = [ 46 | autoprefixer({ browsers: ['last 1 version'] }), 47 | postcssNeat({}), 48 | postcssNested, 49 | postcssVars, 50 | postcssMinMax 51 | ]; 52 | 53 | return gulp.src('./demo/input.scss') 54 | .pipe(postcss(processors)) 55 | .pipe(concat('output.css')) 56 | .pipe(gulp.dest('./demo/')); 57 | }); 58 | 59 | gulp.task('default', ['lint', 'test']); 60 | -------------------------------------------------------------------------------- /lib/core/functions.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var functions = { 7 | // Convert to percentage 8 | 9 | percentage: function percentage() { 10 | var value = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; 11 | 12 | value = +value; 13 | return (value <= 1 ? (value * 100).toFixed(8) : value) + '%'; 14 | }, 15 | 16 | 17 | // Simple clearfix 18 | clearfix: function clearfix() { 19 | return { 20 | '*zoom': 1, 21 | '&:before, &:after': { 22 | 'content': '" "', 23 | 'display': 'table' 24 | }, 25 | '&:after': { 26 | 'clear': 'both' 27 | } 28 | }; 29 | } 30 | }; 31 | 32 | functions = Object.assign(functions, { 33 | // Sets layout direction and layout opposite direction to `@direction` 34 | // and `@opposite-direction` accordingly. 35 | 36 | getDirection: function getDirection(layout) { 37 | return { 38 | direction: layout === 'LTR' ? 'right' : 'left', 39 | oppositeDirection: layout === 'LTR' ? 'left' : 'right' 40 | }; 41 | }, 42 | 43 | 44 | // Sets neat grid column's width to `@column-width`. 45 | flexWidth: function flexWidth(columns, containerColumns, column, gutter) { 46 | columns = +columns; 47 | containerColumns = +containerColumns; 48 | column = +column.replace('em', '').replace('px', ''); 49 | gutter = +gutter.replace('em', '').replace('px', ''); 50 | 51 | var tmpWidth = columns * column + (columns - 1) * gutter; 52 | var tmpContainerWidth = containerColumns * column + (containerColumns - 1) * gutter; 53 | 54 | return tmpWidth / tmpContainerWidth; // columnWidth 55 | }, 56 | 57 | 58 | // Sets neat grid column's gutter (the white space between two columns) to `@column-gutter`. 59 | flexGutter: function flexGutter(containerColumns, column, gutter) { 60 | containerColumns = +containerColumns; 61 | column = +column.replace('em', '').replace('px', ''); 62 | gutter = +gutter.replace('em', '').replace('px', ''); 63 | 64 | var tmpContainerWidth = containerColumns * column + (containerColumns - 1) * gutter; 65 | 66 | return gutter / tmpContainerWidth; // columnGutter 67 | } 68 | }); 69 | 70 | exports.default = functions; 71 | //# sourceMappingURL=functions.es6.js.map 72 | -------------------------------------------------------------------------------- /lib/core/functions.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["core/functions.es6.js"],"names":[],"mappings":"AAAA;;;;;AAEA,IAAI,YAAY;;;AAEd,oCAAsB;QAAX,8DAAQ,iBAAG;;AACpB,YAAQ,CAAC,KAAD,CADY;AAEpB,YAAU,SAAS,CAAT,GAAa,CAAC,QAAQ,GAAR,CAAD,CAAc,OAAd,CAAsB,CAAtB,CAAb,GAAwC,KAAxC,OAAV,CAFoB;GAFR;;;;AAQd,gCAAW;AACT,WAAO;AACL,eAAS,CAAT;AACA,2BAAqB;AACnB,mBAAW,KAAX;AACA,mBAAW,OAAX;OAFF;AAIA,iBAAW;AACT,iBAAS,MAAT;OADF;KANF,CADS;GARG;CAAZ;;AAsBJ,YAAY,OAAO,MAAP,CAAc,SAAd,EAAyB;;;;AAGnC,sCAAa,QAAQ;AACnB,WAAO;AACL,iBAAW,WAAW,KAAX,GAAmB,OAAnB,GAA6B,MAA7B;AACX,yBAAmB,WAAW,KAAX,GAAmB,MAAnB,GAA4B,OAA5B;KAFrB,CADmB;GAHc;;;;AAWnC,gCAAU,SAAS,kBAAkB,QAAQ,QAAQ;AACnD,cAAU,CAAC,OAAD,CADyC;AAEnD,uBAAmB,CAAC,gBAAD,CAFgC;AAGnD,aAAS,CAAC,OAAO,OAAP,CAAe,IAAf,EAAqB,EAArB,EAAyB,OAAzB,CAAiC,IAAjC,EAAuC,EAAvC,CAAD,CAH0C;AAInD,aAAS,CAAC,OAAO,OAAP,CAAe,IAAf,EAAqB,EAArB,EAAyB,OAAzB,CAAiC,IAAjC,EAAuC,EAAvC,CAAD,CAJ0C;;AAMnD,QAAI,WAAW,UAAU,MAAV,GAAmB,CAAC,UAAU,CAAV,CAAD,GAAgB,MAAhB,CANiB;AAOnD,QAAI,oBAAoB,mBAAmB,MAAnB,GAA4B,CAAC,mBAAmB,CAAnB,CAAD,GAAyB,MAAzB,CAPD;;AASnD,WAAO,WAAW,iBAAX;AAT4C,GAXlB;;;;AAwBnC,kCAAW,kBAAkB,QAAQ,QAAQ;AAC3C,uBAAmB,CAAC,gBAAD,CADwB;AAE3C,aAAS,CAAC,OAAO,OAAP,CAAe,IAAf,EAAqB,EAArB,EAAyB,OAAzB,CAAiC,IAAjC,EAAuC,EAAvC,CAAD,CAFkC;AAG3C,aAAS,CAAC,OAAO,OAAP,CAAe,IAAf,EAAqB,EAArB,EAAyB,OAAzB,CAAiC,IAAjC,EAAuC,EAAvC,CAAD,CAHkC;;AAK3C,QAAI,oBAAoB,mBAAmB,MAAnB,GAA4B,CAAC,mBAAmB,CAAnB,CAAD,GAAyB,MAAzB,CALT;;AAO3C,WAAO,SAAS,iBAAT;AAPoC,GAxBV;CAAzB,CAAZ;;kBAmCe","file":"core/functions.es6.js","sourcesContent":["'use strict';\n\nlet functions = {\n // Convert to percentage\n percentage(value = 0) {\n value = +value;\n return `${value <= 1 ? (value * 100).toFixed(8) : value}%`;\n },\n\n // Simple clearfix\n clearfix() {\n return {\n '*zoom': 1,\n '&:before, &:after': {\n 'content': '\" \"',\n 'display': 'table'\n },\n '&:after': {\n 'clear': 'both'\n }\n };\n }\n};\n\nfunctions = Object.assign(functions, {\n // Sets layout direction and layout opposite direction to `@direction`\n // and `@opposite-direction` accordingly.\n getDirection(layout) {\n return {\n direction: layout === 'LTR' ? 'right' : 'left',\n oppositeDirection: layout === 'LTR' ? 'left' : 'right'\n };\n },\n\n // Sets neat grid column's width to `@column-width`.\n flexWidth(columns, containerColumns, column, gutter) {\n columns = +columns;\n containerColumns = +containerColumns;\n column = +column.replace('em', '').replace('px', '');\n gutter = +gutter.replace('em', '').replace('px', '');\n\n var tmpWidth = columns * column + (columns - 1) * gutter;\n var tmpContainerWidth = containerColumns * column + (containerColumns - 1) * gutter;\n\n return tmpWidth / tmpContainerWidth; // columnWidth\n },\n\n // Sets neat grid column's gutter (the white space between two columns) to `@column-gutter`.\n flexGutter(containerColumns, column, gutter) {\n containerColumns = +containerColumns;\n column = +column.replace('em', '').replace('px', '');\n gutter = +gutter.replace('em', '').replace('px', '');\n\n var tmpContainerWidth = containerColumns * column + (containerColumns - 1) * gutter;\n\n return gutter / tmpContainerWidth; // columnGutter\n }\n});\n\nexport default functions;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/core/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _functionsEs = require('./functions.es6.js'); 8 | 9 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 10 | 11 | var _variablesEs = require('./variables.es6.js'); 12 | 13 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | exports.default = { 18 | functions: _functionsEs2.default, 19 | variables: _variablesEs2.default 20 | }; 21 | //# sourceMappingURL=index.js.map 22 | -------------------------------------------------------------------------------- /lib/core/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["core/index.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;;;kBAEe;AACb,kCADa;AAEb,kCAFa","file":"core/index.js","sourcesContent":["'use strict';\n\nimport functions from './functions.es6.js';\nimport variables from './variables.es6.js';\n\nexport default {\n functions,\n variables\n};\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/core/variables.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var locals = { 7 | defaultEmSize: 1, 8 | goldenRatio: 1.618 9 | }; 10 | 11 | var variables = { 12 | // Sets the default display mode. Can be `block`, `table` or `block-collapse`. 13 | neatDefaultDisplay: 'block', 14 | 15 | // Sets the default layout direction of the grid. Can be `LTR` or `RTL`. 16 | neatDefaultDirection: 'LTR', 17 | 18 | // Sets the number of columns the element spans. Its value can be overridden inside a mixin using the `@columns` variable. 19 | neatElementColumns: 1, 20 | 21 | // Sets the total number of columns in the grid. Its value can be overridden inside a mixin using the `@container-columns` variable. 22 | neatGridColumns: 12, 23 | 24 | // Sets the relative width of a single grid column. The unit used should be the same one used to define `@neat-gutter-width`. 25 | neatColumnWidth: (locals.defaultEmSize * locals.goldenRatio * locals.goldenRatio * locals.goldenRatio).toString() + 'em', 26 | 27 | // Sets the relative width of a single grid gutter. The unit used should be the same one used to define `@neat-column-width`. 28 | neatGutterWidth: (locals.defaultEmSize * locals.goldenRatio).toString() + 'em', 29 | 30 | // Sets the max-width property of the element that includes `@neat-outer-container`. 31 | neatMaxWidth: (1024 / 16 * locals.defaultEmSize).toString() + 'em', 32 | 33 | // Sets the background color for the debugging grid. 34 | debugGridColor: '#ecf0f1', 35 | 36 | // Sets the default location of the debugging grid. 37 | debugGridLocation: 'after' 38 | }; 39 | 40 | exports.default = variables; 41 | //# sourceMappingURL=variables.es6.js.map 42 | -------------------------------------------------------------------------------- /lib/core/variables.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["core/variables.es6.js"],"names":[],"mappings":"AAAA;;;;;AAEA,IAAM,SAAS;AACb,iBAAe,CAAf;AACA,eAAa,KAAb;CAFI;;AAKN,IAAI,YAAY;;AAEd,sBAAoB,OAApB;;;AAGA,wBAAsB,KAAtB;;;AAGA,sBAAoB,CAApB;;;AAGA,mBAAiB,EAAjB;;;AAGA,mBAAiB,CAAC,MAAE,CAAO,aAAP,GAAuB,OAAO,WAAP,GAAsB,OAAO,WAAP,GAAsB,OAAO,WAAP,CAAtE,CAA0F,QAA1F,KAAuG,IAAvG;;;AAGjB,mBAAiB,CAAC,OAAO,aAAP,GAAuB,OAAO,WAAP,CAAxB,CAA4C,QAA5C,KAAyD,IAAzD;;;AAGjB,gBAAc,CAAC,IAAC,GAAO,EAAP,GAAa,OAAO,aAAP,CAAf,CAAqC,QAArC,KAAkD,IAAlD;;;AAGd,kBAAgB,SAAhB;;;AAGA,qBAAmB,OAAnB;CA1BE;;kBA6BW","file":"core/variables.es6.js","sourcesContent":["'use strict';\n\nconst locals = {\n defaultEmSize: 1,\n goldenRatio: 1.618\n};\n\nlet variables = {\n // Sets the default display mode. Can be `block`, `table` or `block-collapse`.\n neatDefaultDisplay: 'block',\n\n // Sets the default layout direction of the grid. Can be `LTR` or `RTL`.\n neatDefaultDirection: 'LTR',\n\n // Sets the number of columns the element spans. Its value can be overridden inside a mixin using the `@columns` variable.\n neatElementColumns: 1,\n\n // Sets the total number of columns in the grid. Its value can be overridden inside a mixin using the `@container-columns` variable.\n neatGridColumns: 12,\n\n // Sets the relative width of a single grid column. The unit used should be the same one used to define `@neat-gutter-width`.\n neatColumnWidth: (((locals.defaultEmSize * locals.goldenRatio) * locals.goldenRatio) * locals.goldenRatio).toString() + 'em',\n\n // Sets the relative width of a single grid gutter. The unit used should be the same one used to define `@neat-column-width`.\n neatGutterWidth: (locals.defaultEmSize * locals.goldenRatio).toString() + 'em',\n\n // Sets the max-width property of the element that includes `@neat-outer-container`.\n neatMaxWidth: ((1024 / 16) * locals.defaultEmSize).toString() + 'em',\n\n // Sets the background color for the debugging grid.\n debugGridColor: '#ecf0f1',\n\n // Sets the default location of the debugging grid.\n debugGridLocation: 'after'\n};\n\nexport default variables;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/fill-parent.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | // Forces the element to fill its parent container. 14 | // 15 | // @example - PostCSS Usage 16 | // .element { 17 | // @neat-fill-parent; 18 | // } 19 | // 20 | // @example - CSS Output 21 | // .element { 22 | // box-sizing: border-box; 23 | // width: 100%; 24 | // } 25 | // 26 | 27 | var fillParent = function fillParent() { 28 | var options = arguments.length <= 0 || arguments[0] === undefined ? _variablesEs2.default : arguments[0]; 29 | 30 | return { 31 | 'box-sizing': 'border-box', 32 | 'width': '100%' 33 | }; 34 | }; 35 | 36 | exports.default = fillParent; 37 | //# sourceMappingURL=fill-parent.es6.js.map 38 | -------------------------------------------------------------------------------- /lib/grid/fill-parent.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/fill-parent.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;;;;;;;;;;;;;;;;;AAgBA,IAAI,aAAa,SAAb,UAAa,GAAyB;MAAxB,qGAAwB;;AACxC,SAAO;AACL,kBAAc,YAAd;AACA,aAAS,MAAT;GAFF,CADwC;CAAzB;;kBAOF","file":"grid/fill-parent.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\n\n// Forces the element to fill its parent container.\n//\n// @example - PostCSS Usage\n// .element {\n// @neat-fill-parent;\n// }\n//\n// @example - CSS Output\n// .element {\n// box-sizing: border-box;\n// width: 100%;\n// }\n//\n\nlet fillParent = (options = variables) => {\n return {\n 'box-sizing': 'border-box',\n 'width': '100%'\n };\n};\n\nexport default fillParent;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _fillParentEs = require('./fill-parent.es6.js'); 8 | 9 | var _fillParentEs2 = _interopRequireDefault(_fillParentEs); 10 | 11 | var _omegaEs = require('./omega.es6.js'); 12 | 13 | var _omegaEs2 = _interopRequireDefault(_omegaEs); 14 | 15 | var _outerContainerEs = require('./outer-container.es6.js'); 16 | 17 | var _outerContainerEs2 = _interopRequireDefault(_outerContainerEs); 18 | 19 | var _padEs = require('./pad.es6.js'); 20 | 21 | var _padEs2 = _interopRequireDefault(_padEs); 22 | 23 | var _rowEs = require('./row.es6.js'); 24 | 25 | var _rowEs2 = _interopRequireDefault(_rowEs); 26 | 27 | var _shiftEs = require('./shift.es6.js'); 28 | 29 | var _shiftEs2 = _interopRequireDefault(_shiftEs); 30 | 31 | var _showGridEs = require('./show-grid.es6.js'); 32 | 33 | var _showGridEs2 = _interopRequireDefault(_showGridEs); 34 | 35 | var _spanColumnsEs = require('./span-columns.es6.js'); 36 | 37 | var _spanColumnsEs2 = _interopRequireDefault(_spanColumnsEs); 38 | 39 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 40 | 41 | exports.default = { 42 | fillParent: _fillParentEs2.default, 43 | omega: _omegaEs2.default, 44 | outerContainer: _outerContainerEs2.default, 45 | pad: _padEs2.default, 46 | row: _rowEs2.default, 47 | shift: _shiftEs2.default, 48 | showGrid: _showGridEs2.default, 49 | spanColumns: _spanColumnsEs2.default 50 | }; 51 | //# sourceMappingURL=index.js.map 52 | -------------------------------------------------------------------------------- /lib/grid/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/index.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;;;;;kBAEe;AACb,oCADa;AAEb,0BAFa;AAGb,4CAHa;AAIb,sBAJa;AAKb,sBALa;AAMb,0BANa;AAOb,gCAPa;AAQb,sCARa","file":"grid/index.js","sourcesContent":["'use strict';\n\nimport fillParent from './fill-parent.es6.js';\nimport omega from './omega.es6.js';\nimport outerContainer from './outer-container.es6.js';\nimport pad from './pad.es6.js';\nimport row from './row.es6.js';\nimport shift from './shift.es6.js';\nimport showGrid from './show-grid.es6.js';\nimport spanColumns from './span-columns.es6.js';\n\nexport default {\n fillParent,\n omega,\n outerContainer,\n pad,\n row,\n shift,\n showGrid,\n spanColumns\n};\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/omega.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | var _functionsEs = require('../core/functions.es6.js'); 12 | 13 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 18 | 19 | // Removes the element's gutter margin, regardless of its position in the grid hierarchy or display property. 20 | // It can target a specific element, or every `nth-child` occurrence. Works only with `block` layouts. 21 | // 22 | // @query 23 | // Supported arguments are `nth-child` selectors (targets a specific pseudo element) and `auto` (targets `last-child`). 24 | // 25 | // When passed an `nth-child` argument of type `*n` with `block` display, the omega mixin automatically 26 | // adds a clear to the `*n+1` th element. 27 | // 28 | // Note that composite arguments such as `2n+1` do not support this feature. 29 | // 30 | // @direction 31 | // Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left). 32 | // 33 | // @example - PostCSS Usage 34 | // .element { 35 | // @neat-omega; 36 | // } 37 | // 38 | // .nth-element { 39 | // @neat-omega 4n; 40 | // } 41 | // 42 | // .auto-element { 43 | // @neat-omega auto; 44 | // } 45 | // 46 | // @example - CSS Output 47 | // .element { 48 | // margin-right: 0; 49 | // } 50 | // 51 | // .nth-element:nth-child(4n) { 52 | // margin-right: 0; 53 | // } 54 | // 55 | // .nth-element:nth-child(4n+1) { 56 | // clear: left; 57 | // } 58 | // 59 | // .auto-element:last-child { 60 | // margin-right: 0; 61 | // } 62 | // 63 | 64 | var omega = function omega(query, direction) { 65 | var options = arguments.length <= 2 || arguments[2] === undefined ? _variablesEs2.default : arguments[2]; 66 | 67 | direction = direction || options.neatDefaultDirection; 68 | 69 | var directions = _functionsEs2.default.getDirection(direction); 70 | if (!query) { 71 | return _defineProperty({}, 'margin-' + directions.direction, 0); 72 | } else if (query === 'auto') { 73 | return { 74 | '&:last-child': _defineProperty({}, 'margin-' + directions.direction, 0) 75 | }; 76 | } else if (query) { 77 | var result = _defineProperty({}, '&:nth-child(' + query + ')', _defineProperty({}, 'margin-' + directions.direction, 0)); 78 | 79 | if (query.indexOf('n') >= 0) { 80 | result['&:nth-child(' + query + ' + 1)'] = { 81 | 'clear': directions.oppositeDirection 82 | }; 83 | } 84 | 85 | return result; 86 | } 87 | }; 88 | 89 | exports.default = omega; 90 | //# sourceMappingURL=omega.es6.js.map 91 | -------------------------------------------------------------------------------- /lib/grid/omega.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/omega.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAI,QAAQ,SAAR,KAAQ,CAAC,KAAD,EAAQ,SAAR,EAA2C;MAAxB,qGAAwB;;AACrD,cAAY,aAAa,QAAQ,oBAAR,CAD4B;;AAGrD,MAAI,aAAa,sBAAU,YAAV,CAAuB,SAAvB,CAAb,CAHiD;AAIrD,MAAI,CAAC,KAAD,EAAQ;AACV,2CACa,WAAW,SAAX,EAAyB,EADtC,CADU;GAAZ,MAIO,IAAI,UAAU,MAAV,EAAkB;AAC3B,WAAO;AACL,sDACa,WAAW,SAAX,EAAyB,EADtC;KADF,CAD2B;GAAtB,MAMA,IAAI,KAAJ,EAAW;AAChB,QAAI,8CACc,6CACH,WAAW,SAAX,EAAyB,GAFpC,CADY;;AAOhB,QAAI,MAAM,OAAN,CAAc,GAAd,KAAsB,CAAtB,EAAyB;AAC3B,8BAAsB,eAAtB,IAAsC;AACpC,iBAAS,WAAW,iBAAX;OADX,CAD2B;KAA7B;;AAMA,WAAO,MAAP,CAbgB;GAAX;CAdG;;kBA+BG","file":"grid/omega.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\nimport functions from '../core/functions.es6.js';\n\n// Removes the element's gutter margin, regardless of its position in the grid hierarchy or display property.\n// It can target a specific element, or every `nth-child` occurrence. Works only with `block` layouts.\n//\n// @query\n// Supported arguments are `nth-child` selectors (targets a specific pseudo element) and `auto` (targets `last-child`).\n//\n// When passed an `nth-child` argument of type `*n` with `block` display, the omega mixin automatically\n// adds a clear to the `*n+1` th element.\n//\n// Note that composite arguments such as `2n+1` do not support this feature.\n//\n// @direction\n// Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left).\n//\n// @example - PostCSS Usage\n// .element {\n// @neat-omega;\n// }\n//\n// .nth-element {\n// @neat-omega 4n;\n// }\n//\n// .auto-element {\n// @neat-omega auto;\n// }\n//\n// @example - CSS Output\n// .element {\n// margin-right: 0;\n// }\n//\n// .nth-element:nth-child(4n) {\n// margin-right: 0;\n// }\n//\n// .nth-element:nth-child(4n+1) {\n// clear: left;\n// }\n//\n// .auto-element:last-child {\n// margin-right: 0;\n// }\n//\n\nlet omega = (query, direction, options = variables) => {\n direction = direction || options.neatDefaultDirection;\n\n let directions = functions.getDirection(direction);\n if (!query) {\n return {\n [`margin-${directions.direction}`]: 0\n };\n } else if (query === 'auto') {\n return {\n '&:last-child': {\n [`margin-${directions.direction}`]: 0\n }\n };\n } else if (query) {\n let result = {\n [`&:nth-child(${query})`]: {\n [`margin-${directions.direction}`]: 0\n }\n };\n\n if (query.indexOf('n') >= 0) {\n result[`&:nth-child(${query} + 1)`] = {\n 'clear': directions.oppositeDirection\n };\n }\n\n return result;\n }\n};\n\nexport default omega;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/outer-container.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | var _functionsEs = require('../core/functions.es6.js'); 12 | 13 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | // Makes an element a outer container by centring it in the viewport, clearing its floats, and setting its `max-width`. 18 | // Although optional, using `outer-container` is recommended. The mixin can be called on more than one element per page, 19 | // as long as they are not nested. 20 | // 21 | // @local-max-width 22 | // Max width to be applied to the element. Can be a percentage or a measure. 23 | // 24 | // @example - PostCSS Usage 25 | // .element { 26 | // @neat-outer-container 100%; 27 | // } 28 | // 29 | // @example - CSS Output 30 | // .element { 31 | // *zoom: 1; 32 | // max-width: 100%; 33 | // margin-left: auto; 34 | // margin-right: auto; 35 | // } 36 | // 37 | // .element:before, 38 | // .element:after { 39 | // content: " "; 40 | // display: table; 41 | // } 42 | // 43 | // .element:after { 44 | // clear: both; 45 | // } 46 | // 47 | 48 | var outerContainer = function outerContainer(maxWidth) { 49 | var options = arguments.length <= 1 || arguments[1] === undefined ? _variablesEs2.default : arguments[1]; 50 | 51 | maxWidth = maxWidth || options.neatMaxWidth; 52 | 53 | return Object.assign({ 54 | 'max-width': maxWidth, 55 | 'margin-left': 'auto', 56 | 'margin-right': 'auto' 57 | }, _functionsEs2.default.clearfix()); 58 | }; 59 | 60 | exports.default = outerContainer; 61 | //# sourceMappingURL=outer-container.es6.js.map 62 | -------------------------------------------------------------------------------- /lib/grid/outer-container.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/outer-container.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAI,iBAAiB,SAAjB,cAAiB,CAAC,QAAD,EAAmC;MAAxB,qGAAwB;;AACtD,aAAW,YAAY,QAAQ,YAAR,CAD+B;;AAGtD,SAAO,OAAO,MAAP,CAAc;AACnB,iBAAa,QAAb;AACA,mBAAe,MAAf;AACA,oBAAgB,MAAhB;GAHK,EAIJ,sBAAU,QAAV,EAJI,CAAP,CAHsD;CAAnC;;kBAUN","file":"grid/outer-container.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\nimport functions from '../core/functions.es6.js';\n\n// Makes an element a outer container by centring it in the viewport, clearing its floats, and setting its `max-width`.\n// Although optional, using `outer-container` is recommended. The mixin can be called on more than one element per page,\n// as long as they are not nested.\n//\n// @local-max-width\n// Max width to be applied to the element. Can be a percentage or a measure.\n//\n// @example - PostCSS Usage\n// .element {\n// @neat-outer-container 100%;\n// }\n//\n// @example - CSS Output\n// .element {\n// *zoom: 1;\n// max-width: 100%;\n// margin-left: auto;\n// margin-right: auto;\n// }\n//\n// .element:before,\n// .element:after {\n// content: \" \";\n// display: table;\n// }\n//\n// .element:after {\n// clear: both;\n// }\n//\n\nlet outerContainer = (maxWidth, options = variables) => {\n maxWidth = maxWidth || options.neatMaxWidth;\n\n return Object.assign({\n 'max-width': maxWidth,\n 'margin-left': 'auto',\n 'margin-right': 'auto'\n }, functions.clearfix());\n};\n\nexport default outerContainer;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/pad.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | var _functionsEs = require('../core/functions.es6.js'); 12 | 13 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | // Adds padding to the element. 18 | // 19 | // @padding 20 | // A list of padding value(s) to use. Passing `default` in the list will result 21 | // in using the gutter width as a padding value. 22 | // 23 | // @example - PostCSS Usage 24 | // .element { 25 | // @neat-pad 30px -20px 10px default; 26 | // } 27 | // 28 | // @example - CSS Output 29 | // .element { 30 | // padding: 30px -20px 10px 2.3576516%; 31 | // } 32 | // 33 | 34 | var pad = function pad() { 35 | var padding = arguments.length <= 0 || arguments[0] === undefined ? 'default' : arguments[0]; 36 | var options = arguments.length <= 1 || arguments[1] === undefined ? _variablesEs2.default : arguments[1]; 37 | 38 | var columnGutter = _functionsEs2.default.percentage(_functionsEs2.default.flexGutter(options.neatGridColumns, options.neatColumnWidth, options.neatGutterWidth)); 39 | var parts = Array.isArray(padding) ? padding : padding.split(' '); 40 | 41 | if (!parts.length) { 42 | parts.push('default'); 43 | } 44 | 45 | return { 46 | 'padding': parts.reduce(function (aggr, value) { 47 | aggr.push(value === 'default' ? columnGutter : value); 48 | return aggr; 49 | }, []).join(' ') 50 | }; 51 | }; 52 | 53 | exports.default = pad; 54 | //# sourceMappingURL=pad.es6.js.map 55 | -------------------------------------------------------------------------------- /lib/grid/pad.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/pad.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;;;;;;;;;;;;;;;;;;;;AAmBA,IAAI,MAAM,SAAN,GAAM,GAA8C;MAA7C,gEAAU,yBAAmC;MAAxB,qGAAwB;;AACtD,MAAI,eAAe,sBAAU,UAAV,CAAqB,sBAAU,UAAV,CAAqB,QAAQ,eAAR,EAAyB,QAAQ,eAAR,EAAyB,QAAQ,eAAR,CAA5F,CAAf,CADkD;AAEtD,MAAI,QAAQ,MAAM,OAAN,CAAc,OAAd,IAAyB,OAAzB,GAAmC,QAAQ,KAAR,CAAc,GAAd,CAAnC,CAF0C;;AAItD,MAAI,CAAC,MAAM,MAAN,EAAc;AACjB,UAAM,IAAN,CAAW,SAAX,EADiB;GAAnB;;AAIA,SAAO;AACL,eAAW,MAAM,MAAN,CAAa,UAAC,IAAD,EAAO,KAAP,EAAiB;AACvC,WAAK,IAAL,CAAU,UAAU,SAAV,GAAsB,YAAtB,GAAqC,KAArC,CAAV,CADuC;AAEvC,aAAO,IAAP,CAFuC;KAAjB,EAGrB,EAHQ,EAGJ,IAHI,CAGC,GAHD,CAAX;GADF,CARsD;CAA9C;;kBAgBK","file":"grid/pad.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\nimport functions from '../core/functions.es6.js';\n\n// Adds padding to the element.\n//\n// @padding\n// A list of padding value(s) to use. Passing `default` in the list will result\n// in using the gutter width as a padding value.\n//\n// @example - PostCSS Usage\n// .element {\n// @neat-pad 30px -20px 10px default;\n// }\n//\n// @example - CSS Output\n// .element {\n// padding: 30px -20px 10px 2.3576516%;\n// }\n//\n\nlet pad = (padding = 'default', options = variables) => {\n let columnGutter = functions.percentage(functions.flexGutter(options.neatGridColumns, options.neatColumnWidth, options.neatGutterWidth));\n let parts = Array.isArray(padding) ? padding : padding.split(' ');\n\n if (!parts.length) {\n parts.push('default');\n }\n\n return {\n 'padding': parts.reduce((aggr, value) => {\n aggr.push(value === 'default' ? columnGutter : value);\n return aggr;\n }, []).join(' ')\n };\n};\n\nexport default pad;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/row.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | var _functionsEs = require('../core/functions.es6.js'); 12 | 13 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 14 | 15 | var _fillParentEs = require('./fill-parent.es6.js'); 16 | 17 | var _fillParentEs2 = _interopRequireDefault(_fillParentEs); 18 | 19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 20 | 21 | // Designates the element as a row of columns in the grid layout. It clears the floats on the element and 22 | // sets its display property. Rows can't be nested, but there can be more than one row element 23 | // with different display properties per layout. 24 | // 25 | // @display 26 | // Sets the display property of the element and the display context that 27 | // will be used by its children. Can be `block` or `table`. 28 | // 29 | // @direction 30 | // Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left). 31 | // 32 | // @example - PostCSS Usage 33 | // .element { 34 | // @neat-row; 35 | // } 36 | // 37 | // @example - CSS Output 38 | // .element { 39 | // *zoom: 1; 40 | // display: block; 41 | // } 42 | // 43 | // .element:before, 44 | // .element:after { 45 | // content: " "; 46 | // display: table; 47 | // } 48 | // 49 | // .element:after { 50 | // clear: both; 51 | // } 52 | // 53 | 54 | var row = function row(display) { 55 | var options = arguments.length <= 1 || arguments[1] === undefined ? _variablesEs2.default : arguments[1]; 56 | 57 | display = display || options.neatDefaultDisplay; 58 | 59 | if (display === 'table') { 60 | return Object.assign({ 61 | 'display': 'table', 62 | 'table-layout': 'fixed' 63 | }, (0, _fillParentEs2.default)()); 64 | } else { 65 | return Object.assign({ 66 | 'display': 'block' 67 | }, _functionsEs2.default.clearfix()); 68 | } 69 | }; 70 | 71 | exports.default = row; 72 | //# sourceMappingURL=row.es6.js.map 73 | -------------------------------------------------------------------------------- /lib/grid/row.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/row.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,IAAI,MAAM,SAAN,GAAM,CAAC,OAAD,EAAkC;MAAxB,qGAAwB;;AAC1C,YAAU,WAAW,QAAQ,kBAAR,CADqB;;AAG1C,MAAI,YAAY,OAAZ,EAAqB;AACvB,WAAO,OAAO,MAAP,CAAc;AACnB,iBAAW,OAAX;AACA,sBAAgB,OAAhB;KAFK,EAGJ,6BAHI,CAAP,CADuB;GAAzB,MAKO;AACL,WAAO,OAAO,MAAP,CAAc;AACnB,iBAAW,OAAX;KADK,EAEJ,sBAAU,QAAV,EAFI,CAAP,CADK;GALP;CAHQ;;kBAeK","file":"grid/row.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\nimport functions from '../core/functions.es6.js';\nimport fillParent from './fill-parent.es6.js';\n\n// Designates the element as a row of columns in the grid layout. It clears the floats on the element and\n// sets its display property. Rows can't be nested, but there can be more than one row element\n// with different display properties per layout.\n//\n// @display\n// Sets the display property of the element and the display context that\n// will be used by its children. Can be `block` or `table`.\n//\n// @direction\n// Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left).\n//\n// @example - PostCSS Usage\n// .element {\n// @neat-row;\n// }\n//\n// @example - CSS Output\n// .element {\n// *zoom: 1;\n// display: block;\n// }\n//\n// .element:before,\n// .element:after {\n// content: \" \";\n// display: table;\n// }\n//\n// .element:after {\n// clear: both;\n// }\n//\n\nlet row = (display, options = variables) => {\n display = display || options.neatDefaultDisplay;\n\n if (display === 'table') {\n return Object.assign({\n 'display': 'table',\n 'table-layout': 'fixed'\n }, fillParent());\n } else {\n return Object.assign({\n 'display': 'block'\n }, functions.clearfix());\n }\n};\n\nexport default row;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/shift.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | var _functionsEs = require('../core/functions.es6.js'); 12 | 13 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 18 | 19 | // Translates an element horizontally by a number of columns, in a specific nesting context. 20 | // 21 | // @columns 22 | // The number of columns to shift (required). 23 | // 24 | // @container-columns 25 | // The number of columns of the parent element. 26 | // 27 | // @direction 28 | // Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left). 29 | // 30 | // @example - PostCSS Usage 31 | // .element-neg { 32 | // @neat-shift -3 6; 33 | // } 34 | // 35 | // .element-pos { 36 | // @neat-shift 2; 37 | // } 38 | // 39 | // @example - CSS output 40 | // .element-neg { 41 | // margin-left: -52.41457896%; 42 | // } 43 | // 44 | // .element-pos { 45 | // margin-left: 17.0596086%; 46 | // } 47 | // 48 | 49 | var shift = function shift(columns, containerColumns, direction) { 50 | var options = arguments.length <= 3 || arguments[3] === undefined ? _variablesEs2.default : arguments[3]; 51 | 52 | containerColumns = containerColumns || options.neatGridColumns; 53 | direction = direction || options.neatDefaultDirection; 54 | 55 | var directions = _functionsEs2.default.getDirection(direction); 56 | var columnWidth = _functionsEs2.default.flexWidth(1, containerColumns, options.neatColumnWidth, options.neatGutterWidth); 57 | var columnGutter = _functionsEs2.default.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth); 58 | return _defineProperty({}, 'margin-' + directions.oppositeDirection, _functionsEs2.default.percentage(columns * columnWidth + columns * columnGutter)); 59 | }; 60 | 61 | exports.default = shift; 62 | //# sourceMappingURL=shift.es6.js.map 63 | -------------------------------------------------------------------------------- /lib/grid/shift.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/shift.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAI,QAAQ,SAAR,KAAQ,CAAC,OAAD,EAAU,gBAAV,EAA4B,SAA5B,EAA+D;MAAxB,qGAAwB;;AACzE,qBAAmB,oBAAoB,QAAQ,eAAR,CADkC;AAEzE,cAAY,aAAa,QAAQ,oBAAR,CAFgD;;AAIzE,MAAI,aAAa,sBAAU,YAAV,CAAuB,SAAvB,CAAb,CAJqE;AAKzE,MAAI,cAAc,sBAAU,SAAV,CAAoB,CAApB,EAAuB,gBAAvB,EAAyC,QAAQ,eAAR,EAAyB,QAAQ,eAAR,CAAhF,CALqE;AAMzE,MAAI,eAAe,sBAAU,UAAV,CAAqB,gBAArB,EAAuC,QAAQ,eAAR,EAAyB,QAAQ,eAAR,CAA/E,CANqE;AAOzE,yCACa,WAAW,iBAAX,EAAiC,sBAAU,UAAV,CAAqB,UAAU,WAAV,GAAwB,UAAU,YAAV,EAD3F,CAPyE;CAA/D;;kBAYG","file":"grid/shift.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\nimport functions from '../core/functions.es6.js';\n\n// Translates an element horizontally by a number of columns, in a specific nesting context.\n//\n// @columns\n// The number of columns to shift (required).\n//\n// @container-columns\n// The number of columns of the parent element.\n//\n// @direction\n// Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left).\n//\n// @example - PostCSS Usage\n// .element-neg {\n// @neat-shift -3 6;\n// }\n//\n// .element-pos {\n// @neat-shift 2;\n// }\n//\n// @example - CSS output\n// .element-neg {\n// margin-left: -52.41457896%;\n// }\n//\n// .element-pos {\n// margin-left: 17.0596086%;\n// }\n//\n\nlet shift = (columns, containerColumns, direction, options = variables) => {\n containerColumns = containerColumns || options.neatGridColumns;\n direction = direction || options.neatDefaultDirection;\n\n let directions = functions.getDirection(direction);\n let columnWidth = functions.flexWidth(1, containerColumns, options.neatColumnWidth, options.neatGutterWidth);\n let columnGutter = functions.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth);\n return {\n [`margin-${directions.oppositeDirection}`]: functions.percentage(columns * columnWidth + columns * columnGutter)\n };\n};\n\nexport default shift;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/show-grid.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | var _functionsEs = require('../core/functions.es6.js'); 12 | 13 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 18 | 19 | // Creates a debugging grid for the parent of columns. Works in conjunction with `@neat-outer-container`. 20 | // 21 | // @columns 22 | // The unitless number of columns the element spans. If is not passed, it is equal to `@neatElementColumns`. 23 | // `@columns` also accepts decimals for when it's necessary to break out of the standard grid. 24 | // E.g. Passing `2.4` in a standard 12 column grid will divide the row into 5 columns. 25 | // 26 | // @container-columns 27 | // The number of columns the parent element spans. If is not passed, it is equal to `@neatGridColumns`, 28 | // the total number of columns in the grid. 29 | // 30 | // @location 31 | // The location of where the grid will be applied to: ['before', 'after' or 'background'] 32 | // 33 | // @example - PostCSS Usage 34 | // .element { 35 | // @neat-outer-container; 36 | // @neat-show-grid 4 12; 37 | // } 38 | // 39 | // @example - CSS Output 40 | // .element { 41 | // *zoom: 1; 42 | // max-width: 128em; 43 | // margin-left: auto; 44 | // margin-right: auto; 45 | // } 46 | // .element:before, 47 | // .element:after { 48 | // content: " "; 49 | // display: table; 50 | // } 51 | // .element:after { 52 | // clear: both; 53 | // background: linear-gradient(to right, 54 | // #ecf0f1 0, #ecf0f1 31.7615656%, 55 | // transparent 31.7615656%, transparent 34.1192172%, 56 | // #ecf0f1 34.1192172%, #ecf0f1 65.88078280%, 57 | // transparent 65.88078280%, transparent 68.2384344%, 58 | // #ecf0f1 68.2384344%, #ecf0f1 100%); 59 | // bottom: 0; 60 | // display: block; 61 | // left: 0; 62 | // position: absolute; 63 | // right: 0; 64 | // top: 0 65 | // } 66 | // 67 | 68 | var generateArray = function generateArray() { 69 | var length = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; 70 | 71 | return Array.from(new Array(length), function (x, i) { 72 | return i; 73 | }); 74 | }; 75 | 76 | var showGrid = function showGrid(columns, containerColumns, location, direction) { 77 | var options = arguments.length <= 4 || arguments[4] === undefined ? _variablesEs2.default : arguments[4]; 78 | 79 | columns = columns || options.neatElementColumns; 80 | containerColumns = containerColumns || options.neatGridColumns; 81 | location = location || options.debugGridLocation; 82 | direction = direction || options.neatDefaultDirection; 83 | 84 | var columnsCount = +(containerColumns / columns); 85 | var directions = _functionsEs2.default.getDirection(direction); 86 | var columnWidth = _functionsEs2.default.flexWidth(columns, containerColumns, options.neatColumnWidth, options.neatGutterWidth); 87 | var columnGutter = _functionsEs2.default.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth); 88 | 89 | var gradient = generateArray(columnsCount).reduce(function (memo, idx) { 90 | var startColor = columnWidth * idx + columnGutter * idx; 91 | var endColor = columnWidth * (idx + 1) + columnGutter * idx; 92 | var startBlank = endColor; 93 | var endBlank = columnWidth * (idx + 1) + columnGutter * (idx + 1); 94 | memo.push(options.debugGridColor + ' ' + _functionsEs2.default.percentage(startColor) + ', ' + options.debugGridColor + ' ' + _functionsEs2.default.percentage(endColor)); 95 | if (idx < columnsCount - 1) { 96 | memo.push('transparent ' + _functionsEs2.default.percentage(startBlank) + ', transparent ' + _functionsEs2.default.percentage(endBlank)); 97 | } 98 | return memo; 99 | }, [directions.direction === 'right' ? 'to right' : 'to left']); 100 | 101 | // 'before', 'after' or 'background' 102 | if (location === 'background') { 103 | return { 104 | 'background': 'linear-gradient(' + gradient.join(',') + ')' 105 | }; 106 | } else if (location === 'before' || location === 'after') { 107 | return _defineProperty({}, '&:' + location, { 108 | 'background': 'linear-gradient(' + gradient.join(',') + ')', 109 | 'bottom': '0', 110 | 'display': 'block', 111 | 'left': '0', 112 | 'position': 'absolute', 113 | 'right': '0', 114 | 'top': '0' 115 | }); 116 | } 117 | }; 118 | 119 | exports.default = showGrid; 120 | //# sourceMappingURL=show-grid.es6.js.map 121 | -------------------------------------------------------------------------------- /lib/grid/show-grid.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/show-grid.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,IAAM,gBAAgB,SAAhB,aAAgB,GAAgB;MAAf,+DAAS,iBAAM;;AACpC,SAAO,MAAM,IAAN,CAAW,IAAI,KAAJ,CAAU,MAAV,CAAX,EAA8B,UAAC,CAAD,EAAI,CAAJ;WAAU;GAAV,CAArC,CADoC;CAAhB;;AAItB,IAAI,WAAW,SAAX,QAAW,CAAC,OAAD,EAAU,gBAAV,EAA4B,QAA5B,EAAsC,SAAtC,EAAyE;MAAxB,qGAAwB;;AACtF,YAAU,WAAW,QAAQ,kBAAR,CADiE;AAEtF,qBAAmB,oBAAoB,QAAQ,eAAR,CAF+C;AAGtF,aAAW,YAAY,QAAQ,iBAAR,CAH+D;AAItF,cAAY,aAAa,QAAQ,oBAAR,CAJ6D;;AAMtF,MAAI,eAAe,EAAE,mBAAmB,OAAnB,CAAF,CANmE;AAOtF,MAAI,aAAa,sBAAU,YAAV,CAAuB,SAAvB,CAAb,CAPkF;AAQtF,MAAI,cAAc,sBAAU,SAAV,CAAoB,OAApB,EAA6B,gBAA7B,EAA+C,QAAQ,eAAR,EAAyB,QAAQ,eAAR,CAAtF,CARkF;AAStF,MAAI,eAAe,sBAAU,UAAV,CAAqB,gBAArB,EAAuC,QAAQ,eAAR,EAAyB,QAAQ,eAAR,CAA/E,CATkF;;AAWtF,MAAI,WAAW,cAAc,YAAd,EAA4B,MAA5B,CAAmC,UAAC,IAAD,EAAO,GAAP,EAAe;AAC/D,QAAI,aAAa,cAAc,GAAd,GAAoB,eAAe,GAAf,CAD0B;AAE/D,QAAI,WAAW,eAAe,MAAM,CAAN,CAAf,GAA0B,eAAe,GAAf,CAFsB;AAG/D,QAAI,aAAa,QAAb,CAH2D;AAI/D,QAAI,WAAW,eAAe,MAAM,CAAN,CAAf,GAA0B,gBAAgB,MAAM,CAAN,CAAhB,CAJsB;AAK/D,SAAK,IAAL,CAAa,QAAQ,cAAR,SAA0B,sBAAU,UAAV,CAAqB,UAArB,WAAqC,QAAQ,cAAR,SAA0B,sBAAU,UAAV,CAAqB,QAArB,CAAtG,EAL+D;AAM/D,QAAI,MAAM,eAAe,CAAf,EAAkB;AAC1B,WAAK,IAAL,kBAAyB,sBAAU,UAAV,CAAqB,UAArB,uBAAiD,sBAAU,UAAV,CAAqB,QAArB,CAA1E,EAD0B;KAA5B;AAGA,WAAO,IAAP,CAT+D;GAAf,EAU/C,CAAC,WAAW,SAAX,KAAyB,OAAzB,GAAmC,UAAnC,GAAgD,SAAhD,CAVW,CAAX;;;AAXkF,MAwBlF,aAAa,YAAb,EAA2B;AAC7B,WAAO;AACL,yCAAiC,SAAS,IAAT,CAAc,GAAd,OAAjC;KADF,CAD6B;GAA/B,MAIO,IAAI,aAAa,QAAb,IAAyB,aAAa,OAAb,EAAsB;AACxD,sCACQ,UAAa;AACjB,yCAAiC,SAAS,IAAT,CAAc,GAAd,OAAjC;AACA,gBAAU,GAAV;AACA,iBAAW,OAAX;AACA,cAAQ,GAAR;AACA,kBAAY,UAAZ;AACA,eAAS,GAAT;AACA,aAAO,GAAP;MARJ,CADwD;GAAnD;CA5BM;;kBA2CA","file":"grid/show-grid.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\nimport functions from '../core/functions.es6.js';\n\n// Creates a debugging grid for the parent of columns. Works in conjunction with `@neat-outer-container`.\n//\n// @columns\n// The unitless number of columns the element spans. If is not passed, it is equal to `@neatElementColumns`.\n// `@columns` also accepts decimals for when it's necessary to break out of the standard grid.\n// E.g. Passing `2.4` in a standard 12 column grid will divide the row into 5 columns.\n//\n// @container-columns\n// The number of columns the parent element spans. If is not passed, it is equal to `@neatGridColumns`,\n// the total number of columns in the grid.\n//\n// @location\n// The location of where the grid will be applied to: ['before', 'after' or 'background']\n//\n// @example - PostCSS Usage\n// .element {\n// @neat-outer-container;\n// @neat-show-grid 4 12;\n// }\n//\n// @example - CSS Output\n// .element {\n// *zoom: 1;\n// max-width: 128em;\n// margin-left: auto;\n// margin-right: auto;\n// }\n// .element:before,\n// .element:after {\n// content: \" \";\n// display: table;\n// }\n// .element:after {\n// clear: both;\n// background: linear-gradient(to right,\n// #ecf0f1 0, #ecf0f1 31.7615656%,\n// transparent 31.7615656%, transparent 34.1192172%,\n// #ecf0f1 34.1192172%, #ecf0f1 65.88078280%,\n// transparent 65.88078280%, transparent 68.2384344%,\n// #ecf0f1 68.2384344%, #ecf0f1 100%);\n// bottom: 0;\n// display: block;\n// left: 0;\n// position: absolute;\n// right: 0;\n// top: 0\n// }\n//\n\nconst generateArray = (length = 0) => {\n return Array.from(new Array(length), (x, i) => i);\n};\n\nlet showGrid = (columns, containerColumns, location, direction, options = variables) => {\n columns = columns || options.neatElementColumns;\n containerColumns = containerColumns || options.neatGridColumns;\n location = location || options.debugGridLocation;\n direction = direction || options.neatDefaultDirection;\n\n let columnsCount = +(containerColumns / columns);\n let directions = functions.getDirection(direction);\n let columnWidth = functions.flexWidth(columns, containerColumns, options.neatColumnWidth, options.neatGutterWidth);\n let columnGutter = functions.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth);\n\n let gradient = generateArray(columnsCount).reduce((memo, idx) => {\n let startColor = columnWidth * idx + columnGutter * idx;\n let endColor = columnWidth * (idx + 1) + columnGutter * idx;\n let startBlank = endColor;\n let endBlank = columnWidth * (idx + 1) + columnGutter * (idx + 1);\n memo.push(`${options.debugGridColor} ${functions.percentage(startColor)}, ${options.debugGridColor} ${functions.percentage(endColor)}`);\n if (idx < columnsCount - 1) {\n memo.push(`transparent ${functions.percentage(startBlank)}, transparent ${functions.percentage(endBlank)}`);\n }\n return memo;\n }, [directions.direction === 'right' ? 'to right' : 'to left']);\n\n // 'before', 'after' or 'background'\n if (location === 'background') {\n return {\n 'background': `linear-gradient(${gradient.join(',')})`\n };\n } else if (location === 'before' || location === 'after') {\n return {\n [`&:${location}`]: {\n 'background': `linear-gradient(${gradient.join(',')})`,\n 'bottom': '0',\n 'display': 'block',\n 'left': '0',\n 'position': 'absolute',\n 'right': '0',\n 'top': '0'\n }\n };\n }\n};\n\nexport default showGrid;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/grid/span-columns.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _variablesEs = require('../core/variables.es6.js'); 8 | 9 | var _variablesEs2 = _interopRequireDefault(_variablesEs); 10 | 11 | var _functionsEs = require('../core/functions.es6.js'); 12 | 13 | var _functionsEs2 = _interopRequireDefault(_functionsEs); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 18 | 19 | // Specifies the number of columns an element should span. If the selector is nested the number of columns 20 | // of its parent element should be passed as an argument as well. 21 | // 22 | // @columns 23 | // The unitless number of columns the element spans. If is not passed, it is equal to `@neatElementColumns`. 24 | // `@columns` also accepts decimals for when it's necessary to break out of the standard grid. 25 | // E.g. Passing `2.4` in a standard 12 column grid will divide the row into 5 columns. 26 | // 27 | // @container-columns 28 | // The number of columns the parent element spans. If is not passed, it is equal to `@neatGridColumns`, 29 | // the total number of columns in the grid. 30 | // 31 | // @display 32 | // Sets the display property of the element. By default it sets the display property of the element to `block`. 33 | // If passed `block-collapse`, it also removes the margin gutter by adding it to the element width. 34 | // If passed `table`, it sets the display property to `table-cell` and calculates the width of the 35 | // element without taking gutters into consideration. The result does not align with the block-based grid. 36 | // 37 | // @example - PostCSS Usage 38 | // .element { 39 | // @neat-span-columns 6; 40 | // 41 | // .nested-element { 42 | // @neat-span-columns 2 6; 43 | // } 44 | // } 45 | // 46 | // @example - CSS Output 47 | // .element { 48 | // display: block; 49 | // float: left; 50 | // margin-right: 2.3576516%; 51 | // width: 48.8211742%; 52 | // } 53 | // 54 | // .element:last-child { 55 | // margin-right: 0; 56 | // } 57 | // 58 | // .element .nested-element { 59 | // display: block; 60 | // float: left; 61 | // margin-right: 4.82915791%; 62 | // width: 30.11389472%; 63 | // } 64 | // 65 | // .element .nested-element:last-child { 66 | // margin-right: 0; 67 | // } 68 | // 69 | 70 | var spanColumns = function spanColumns(columns, containerColumns, display, direction) { 71 | var options = arguments.length <= 4 || arguments[4] === undefined ? _variablesEs2.default : arguments[4]; 72 | 73 | columns = columns || options.neatElementColumns; 74 | containerColumns = containerColumns || options.neatGridColumns; 75 | display = display || options.neatDefaultDisplay; 76 | direction = direction || options.neatDefaultDirection; 77 | 78 | var directions = _functionsEs2.default.getDirection(direction); 79 | var columnWidth = _functionsEs2.default.flexWidth(columns, containerColumns, options.neatColumnWidth, options.neatGutterWidth); 80 | var columnGutter = _functionsEs2.default.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth); 81 | 82 | if (display === 'table') { 83 | return { 84 | 'display': 'table-cell', 85 | 'width': _functionsEs2.default.percentage(columns / containerColumns) 86 | }; 87 | } else if (display === 'block-collapse') { 88 | return { 89 | 'display': 'block', 90 | 'float': directions.oppositeDirection, 91 | 'width': _functionsEs2.default.percentage(columnWidth + columnGutter), 92 | // --- 93 | '&:last-child': { 94 | 'width': _functionsEs2.default.percentage(columnWidth) 95 | } 96 | }; 97 | } else { 98 | var _ref; 99 | 100 | return _ref = { 101 | 'display': 'block', 102 | 'float': directions.oppositeDirection 103 | }, _defineProperty(_ref, 'margin-' + directions.direction, _functionsEs2.default.percentage(columnGutter)), _defineProperty(_ref, 'width', _functionsEs2.default.percentage(columnWidth)), _defineProperty(_ref, '&:last-child', _defineProperty({}, 'margin-' + directions.direction, 0)), _ref; 104 | } 105 | }; 106 | 107 | exports.default = spanColumns; 108 | //# sourceMappingURL=span-columns.es6.js.map 109 | -------------------------------------------------------------------------------- /lib/grid/span-columns.es6.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["grid/span-columns.es6.js"],"names":[],"mappings":"AAAA;;;;;;AAEA;;;;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,IAAI,cAAc,SAAd,WAAc,CAAC,OAAD,EAAU,gBAAV,EAA4B,OAA5B,EAAqC,SAArC,EAAwE;MAAxB,qGAAwB;;AACxF,YAAU,WAAW,QAAQ,kBAAR,CADmE;AAExF,qBAAmB,oBAAoB,QAAQ,eAAR,CAFiD;AAGxF,YAAU,WAAW,QAAQ,kBAAR,CAHmE;AAIxF,cAAY,aAAa,QAAQ,oBAAR,CAJ+D;;AAMxF,MAAI,aAAa,sBAAU,YAAV,CAAuB,SAAvB,CAAb,CANoF;AAOxF,MAAI,cAAc,sBAAU,SAAV,CAAoB,OAApB,EAA6B,gBAA7B,EAA+C,QAAQ,eAAR,EAAyB,QAAQ,eAAR,CAAtF,CAPoF;AAQxF,MAAI,eAAe,sBAAU,UAAV,CAAqB,gBAArB,EAAuC,QAAQ,eAAR,EAAyB,QAAQ,eAAR,CAA/E,CARoF;;AAUxF,MAAI,YAAY,OAAZ,EAAqB;AACvB,WAAO;AACL,iBAAW,YAAX;AACA,eAAS,sBAAU,UAAV,CAAqB,UAAU,gBAAV,CAA9B;KAFF,CADuB;GAAzB,MAKO,IAAI,YAAY,gBAAZ,EAA8B;AACvC,WAAO;AACL,iBAAW,OAAX;AACA,eAAS,WAAW,iBAAX;AACT,eAAS,sBAAU,UAAV,CAAqB,cAAc,YAAd,CAA9B;;AAEA,sBAAgB;AACd,iBAAS,sBAAU,UAAV,CAAqB,WAArB,CAAT;OADF;KALF,CADuC;GAAlC,MAUA;;;AACL;AACE,iBAAW,OAAX;AACA,eAAS,WAAW,iBAAX;yCACE,WAAW,SAAX,EAAyB,sBAAU,UAAV,CAAqB,YAArB,0BACpC,SAAS,sBAAU,UAAV,CAAqB,WAArB,0BAET,gDACa,WAAW,SAAX,EAAyB,SAPxC,CADK;GAVA;CAfS;;kBAuCH","file":"grid/span-columns.es6.js","sourcesContent":["'use strict';\n\nimport variables from '../core/variables.es6.js';\nimport functions from '../core/functions.es6.js';\n\n// Specifies the number of columns an element should span. If the selector is nested the number of columns\n// of its parent element should be passed as an argument as well.\n//\n// @columns\n// The unitless number of columns the element spans. If is not passed, it is equal to `@neatElementColumns`.\n// `@columns` also accepts decimals for when it's necessary to break out of the standard grid.\n// E.g. Passing `2.4` in a standard 12 column grid will divide the row into 5 columns.\n//\n// @container-columns\n// The number of columns the parent element spans. If is not passed, it is equal to `@neatGridColumns`,\n// the total number of columns in the grid.\n//\n// @display\n// Sets the display property of the element. By default it sets the display property of the element to `block`.\n// If passed `block-collapse`, it also removes the margin gutter by adding it to the element width.\n// If passed `table`, it sets the display property to `table-cell` and calculates the width of the\n// element without taking gutters into consideration. The result does not align with the block-based grid.\n//\n// @example - PostCSS Usage\n// .element {\n// @neat-span-columns 6;\n//\n// .nested-element {\n// @neat-span-columns 2 6;\n// }\n// }\n//\n// @example - CSS Output\n// .element {\n// display: block;\n// float: left;\n// margin-right: 2.3576516%;\n// width: 48.8211742%;\n// }\n//\n// .element:last-child {\n// margin-right: 0;\n// }\n//\n// .element .nested-element {\n// display: block;\n// float: left;\n// margin-right: 4.82915791%;\n// width: 30.11389472%;\n// }\n//\n// .element .nested-element:last-child {\n// margin-right: 0;\n// }\n//\n\nlet spanColumns = (columns, containerColumns, display, direction, options = variables) => {\n columns = columns || options.neatElementColumns;\n containerColumns = containerColumns || options.neatGridColumns;\n display = display || options.neatDefaultDisplay;\n direction = direction || options.neatDefaultDirection;\n\n let directions = functions.getDirection(direction);\n let columnWidth = functions.flexWidth(columns, containerColumns, options.neatColumnWidth, options.neatGutterWidth);\n let columnGutter = functions.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth);\n\n if (display === 'table') {\n return {\n 'display': 'table-cell',\n 'width': functions.percentage(columns / containerColumns)\n };\n } else if (display === 'block-collapse') {\n return {\n 'display': 'block',\n 'float': directions.oppositeDirection,\n 'width': functions.percentage(columnWidth + columnGutter),\n // ---\n '&:last-child': {\n 'width': functions.percentage(columnWidth)\n }\n };\n } else {\n return {\n 'display': 'block',\n 'float': directions.oppositeDirection,\n [`margin-${directions.direction}`]: functions.percentage(columnGutter),\n 'width': functions.percentage(columnWidth),\n // ---\n '&:last-child': {\n [`margin-${directions.direction}`]: 0\n }\n };\n }\n};\n\nexport default spanColumns;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('babel-polyfill'); 4 | module.exports = require('./neat-parser.js').default; 5 | //# sourceMappingURL=index.js.map 6 | -------------------------------------------------------------------------------- /lib/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["index.js"],"names":[],"mappings":"AAAA;;AAEA,QAAQ,gBAAR;AACA,OAAO,OAAP,GAAiB,QAAQ,kBAAR,EAA4B,OAA5B","file":"index.js","sourcesContent":["'use strict';\n\nrequire('babel-polyfill');\nmodule.exports = require('./neat-parser.js').default;\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /lib/neat-parser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; 8 | 9 | var _postcss = require('postcss'); 10 | 11 | var _postcss2 = _interopRequireDefault(_postcss); 12 | 13 | var _core = require('./core'); 14 | 15 | var _core2 = _interopRequireDefault(_core); 16 | 17 | var _grid = require('./grid'); 18 | 19 | var _grid2 = _interopRequireDefault(_grid); 20 | 21 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 22 | 23 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 24 | 25 | require('babel-polyfill'); 26 | 27 | var options = {}; 28 | var ampInsertedNodes = {}; 29 | 30 | var atRules = { 31 | 'fill-parent': function fillParent() { 32 | return _grid2.default.fillParent(options); 33 | }, 34 | 'omega': function omega(query, direction) { 35 | return _grid2.default.omega(query, direction, options); 36 | }, 37 | 'outer-container': function outerContainer(maxWidth) { 38 | return _grid2.default.outerContainer(maxWidth, options); 39 | }, 40 | 'pad': function pad() { 41 | for (var _len = arguments.length, padding = Array(_len), _key = 0; _key < _len; _key++) { 42 | padding[_key] = arguments[_key]; 43 | } 44 | 45 | return _grid2.default.pad(padding, options); 46 | }, 47 | 'row': function row(display) { 48 | return _grid2.default.row(display, options); 49 | }, 50 | 'shift': function shift(columns, containerColumns, direction) { 51 | return _grid2.default.shift(columns, containerColumns, direction, options); 52 | }, 53 | 'show-grid': function showGrid(columns, containerColumns, location, direction) { 54 | return _grid2.default.showGrid(columns, containerColumns, location, direction, options); 55 | }, 56 | 'span-columns': function spanColumns(columns, containerColumns, display, direction) { 57 | return _grid2.default.spanColumns(columns, containerColumns, display, direction, options); 58 | } 59 | }; 60 | 61 | var unwrapAmp = function unwrapAmp(nodeSelector, node) { 62 | if (nodeSelector.indexOf('&:') >= 0 && node.name !== 'media') { 63 | return node.selectors.map(function (selector) { 64 | return nodeSelector.replace(/&/g, selector); 65 | }).join(','); 66 | } 67 | return nodeSelector; 68 | }; 69 | 70 | var getGlobalSelector = function getGlobalSelector(node) { 71 | if (node.parent && node.parent.type === 'atrule') { 72 | return node.parent.name + ' ' + node.parent.params + ' ' + node.selector; 73 | } else if (node.name === 'media') { 74 | return getGlobalSelector(node.parent); 75 | } 76 | return node.selector; 77 | }; 78 | 79 | var applyRuleSetToNode = function applyRuleSetToNode(ruleSet, node, currentAtRule) { 80 | Object.keys(ruleSet).forEach(function (prop) { 81 | var rule = ruleSet[prop]; 82 | if ((typeof rule === 'undefined' ? 'undefined' : _typeof(rule)) === 'object') { 83 | if (node.name !== 'media') { 84 | var extRule = _postcss2.default.rule({ selector: unwrapAmp(prop, node) }); 85 | applyRuleSetToNode(rule, extRule); 86 | 87 | var globalSelector = getGlobalSelector(node); 88 | node.parent.insertAfter(ampInsertedNodes[globalSelector] || node, extRule); 89 | ampInsertedNodes[globalSelector] = extRule; 90 | } else { 91 | var mediaNestedRule = _postcss2.default.parse(prop + ' ' + JSON.stringify(rule).replace(/"/g, '')); 92 | node.append(mediaNestedRule); 93 | } 94 | } else { 95 | if (currentAtRule) { 96 | node.insertBefore(currentAtRule, { prop: prop, value: rule }); 97 | } else { 98 | node.append({ prop: prop, value: rule }); 99 | } 100 | } 101 | }); 102 | }; 103 | 104 | exports.default = _postcss2.default.plugin('postcss-neat', function (opts) { 105 | options = Object.assign({}, _core2.default.variables, opts); 106 | return function (root) { 107 | ampInsertedNodes = {}; 108 | root.walkAtRules(/^neat-/i, function (rule) { 109 | var atRule = rule.name.trim().replace('neat-', ''); 110 | if (atRules[atRule]) { 111 | var params = rule.params.trim() ? rule.params.trim().split(' ') : []; 112 | var ruleSet = atRules[atRule].apply(atRules, _toConsumableArray(params)); 113 | applyRuleSetToNode(ruleSet, rule.parent, rule); 114 | } 115 | rule.remove(); 116 | }); 117 | }; 118 | }); 119 | //# sourceMappingURL=neat-parser.js.map 120 | -------------------------------------------------------------------------------- /lib/neat-parser.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["neat-parser.js"],"names":[],"mappings":"AAAA;;;;;;;;AAIA;;;;AACA;;;;AACA;;;;;;;;AAJA,QAAQ,gBAAR;;AAMA,IAAI,UAAU,EAAV;AACJ,IAAI,mBAAmB,EAAnB;;AAEJ,IAAM,UAAU;AACd,uCAAiB;AACf,WAAO,eAAS,UAAT,CAAoB,OAApB,CAAP,CADe;GADH;AAId,0BAAS,OAAO,WAAW;AACzB,WAAO,eAAS,KAAT,CAAe,KAAf,EAAsB,SAAtB,EAAiC,OAAjC,CAAP,CADyB;GAJb;AAOd,6CAAmB,UAAU;AAC3B,WAAO,eAAS,cAAT,CAAwB,QAAxB,EAAkC,OAAlC,CAAP,CAD2B;GAPf;AAUd,wBAAmB;sCAAT;;KAAS;;AACjB,WAAO,eAAS,GAAT,CAAa,OAAb,EAAsB,OAAtB,CAAP,CADiB;GAVL;AAad,sBAAO,SAAS;AACd,WAAO,eAAS,GAAT,CAAa,OAAb,EAAsB,OAAtB,CAAP,CADc;GAbF;AAgBd,0BAAS,SAAS,kBAAkB,WAAW;AAC7C,WAAO,eAAS,KAAT,CAAe,OAAf,EAAwB,gBAAxB,EAA0C,SAA1C,EAAqD,OAArD,CAAP,CAD6C;GAhBjC;AAmBd,iCAAa,SAAS,kBAAkB,UAAU,WAAW;AAC3D,WAAO,eAAS,QAAT,CAAkB,OAAlB,EAA2B,gBAA3B,EAA6C,QAA7C,EAAuD,SAAvD,EAAkE,OAAlE,CAAP,CAD2D;GAnB/C;AAsBd,uCAAgB,SAAS,kBAAkB,SAAS,WAAW;AAC7D,WAAO,eAAS,WAAT,CAAqB,OAArB,EAA8B,gBAA9B,EAAgD,OAAhD,EAAyD,SAAzD,EAAoE,OAApE,CAAP,CAD6D;GAtBjD;CAAV;;AA2BN,IAAM,YAAY,SAAZ,SAAY,CAAC,YAAD,EAAe,IAAf,EAAwB;AACxC,MAAI,aAAa,OAAb,CAAqB,IAArB,KAA8B,CAA9B,IAAmC,KAAK,IAAL,KAAc,OAAd,EAAuB;AAC5D,WAAO,KAAK,SAAL,CAAe,GAAf,CAAmB,UAAC,QAAD,EAAc;AACtC,aAAO,aAAa,OAAb,CAAqB,IAArB,EAA2B,QAA3B,CAAP,CADsC;KAAd,CAAnB,CAEJ,IAFI,CAEC,GAFD,CAAP,CAD4D;GAA9D;AAKA,SAAO,YAAP,CANwC;CAAxB;;AASlB,IAAM,oBAAoB,SAApB,iBAAoB,CAAC,IAAD,EAAU;AAClC,MAAI,KAAK,MAAL,IAAe,KAAK,MAAL,CAAY,IAAZ,KAAqB,QAArB,EAA+B;AAChD,WAAU,KAAK,MAAL,CAAY,IAAZ,SAAoB,KAAK,MAAL,CAAY,MAAZ,SAAsB,KAAK,QAAL,CADJ;GAAlD,MAEO,IAAI,KAAK,IAAL,KAAc,OAAd,EAAuB;AAChC,WAAO,kBAAkB,KAAK,MAAL,CAAzB,CADgC;GAA3B;AAGP,SAAO,KAAK,QAAL,CAN2B;CAAV;;AAS1B,IAAM,qBAAqB,SAArB,kBAAqB,CAAC,OAAD,EAAU,IAAV,EAAgB,aAAhB,EAAkC;AAC3D,SAAO,IAAP,CAAY,OAAZ,EAAqB,OAArB,CAA6B,UAAC,IAAD,EAAU;AACrC,QAAI,OAAO,QAAQ,IAAR,CAAP,CADiC;AAErC,QAAI,QAAO,mDAAP,KAAgB,QAAhB,EAA0B;AAC5B,UAAI,KAAK,IAAL,KAAc,OAAd,EAAuB;AACzB,YAAI,UAAU,kBAAQ,IAAR,CAAa,EAAE,UAAU,UAAU,IAAV,EAAgB,IAAhB,CAAV,EAAf,CAAV,CADqB;AAEzB,2BAAmB,IAAnB,EAAyB,OAAzB,EAFyB;;AAIzB,YAAI,iBAAiB,kBAAkB,IAAlB,CAAjB,CAJqB;AAKzB,aAAK,MAAL,CAAY,WAAZ,CAAwB,iBAAiB,cAAjB,KAAoC,IAApC,EAA0C,OAAlE,EALyB;AAMzB,yBAAiB,cAAjB,IAAmC,OAAnC,CANyB;OAA3B,MAOO;AACL,YAAI,kBAAkB,kBAAQ,KAAR,CAAiB,aAAQ,KAAK,SAAL,CAAe,IAAf,EAAqB,OAArB,CAA6B,IAA7B,EAAmC,EAAnC,CAAzB,CAAlB,CADC;AAEL,aAAK,MAAL,CAAY,eAAZ,EAFK;OAPP;KADF,MAYO;AACL,UAAI,aAAJ,EAAmB;AACjB,aAAK,YAAL,CAAkB,aAAlB,EAAiC,EAAE,UAAF,EAAQ,OAAO,IAAP,EAAzC,EADiB;OAAnB,MAEO;AACL,aAAK,MAAL,CAAY,EAAE,UAAF,EAAQ,OAAO,IAAP,EAApB,EADK;OAFP;KAbF;GAF2B,CAA7B,CAD2D;CAAlC;;kBAyBZ,kBAAQ,MAAR,CAAe,cAAf,EAA+B,UAAC,IAAD,EAAU;AACtD,YAAU,OAAO,MAAP,CAAc,EAAd,EAAkB,eAAS,SAAT,EAAoB,IAAtC,CAAV,CADsD;AAEtD,SAAO,UAAC,IAAD,EAAU;AACf,uBAAmB,EAAnB,CADe;AAEf,SAAK,WAAL,CAAiB,SAAjB,EAA4B,UAAC,IAAD,EAAU;AACpC,UAAI,SAAS,KAAK,IAAL,CAAU,IAAV,GAAiB,OAAjB,CAAyB,OAAzB,EAAkC,EAAlC,CAAT,CADgC;AAEpC,UAAI,QAAQ,MAAR,CAAJ,EAAqB;AACnB,YAAI,SAAS,KAAK,MAAL,CAAY,IAAZ,KAAqB,KAAK,MAAL,CAAY,IAAZ,GAAmB,KAAnB,CAAyB,GAAzB,CAArB,GAAqD,EAArD,CADM;AAEnB,YAAI,UAAU,QAAQ,OAAR,mCAAmB,OAAnB,CAAV,CAFe;AAGnB,2BAAmB,OAAnB,EAA4B,KAAK,MAAL,EAAa,IAAzC,EAHmB;OAArB;AAKA,WAAK,MAAL,GAPoC;KAAV,CAA5B,CAFe;GAAV,CAF+C;CAAV","file":"neat-parser.js","sourcesContent":["'use strict';\n\nrequire('babel-polyfill');\n\nimport postcss from 'postcss';\nimport neatCore from './core';\nimport neatGrid from './grid';\n\nlet options = {};\nlet ampInsertedNodes = {};\n\nconst atRules = {\n 'fill-parent' () {\n return neatGrid.fillParent(options);\n },\n 'omega' (query, direction) {\n return neatGrid.omega(query, direction, options);\n },\n 'outer-container' (maxWidth) {\n return neatGrid.outerContainer(maxWidth, options);\n },\n 'pad' (...padding) {\n return neatGrid.pad(padding, options);\n },\n 'row' (display) {\n return neatGrid.row(display, options);\n },\n 'shift' (columns, containerColumns, direction) {\n return neatGrid.shift(columns, containerColumns, direction, options);\n },\n 'show-grid' (columns, containerColumns, location, direction) {\n return neatGrid.showGrid(columns, containerColumns, location, direction, options);\n },\n 'span-columns' (columns, containerColumns, display, direction) {\n return neatGrid.spanColumns(columns, containerColumns, display, direction, options);\n }\n};\n\nconst unwrapAmp = (nodeSelector, node) => {\n if (nodeSelector.indexOf('&:') >= 0 && node.name !== 'media') {\n return node.selectors.map((selector) => {\n return nodeSelector.replace(/&/g, selector);\n }).join(',');\n }\n return nodeSelector;\n};\n\nconst getGlobalSelector = (node) => {\n if (node.parent && node.parent.type === 'atrule') {\n return `${node.parent.name} ${node.parent.params} ${node.selector}`;\n } else if (node.name === 'media') {\n return getGlobalSelector(node.parent);\n }\n return node.selector;\n};\n\nconst applyRuleSetToNode = (ruleSet, node, currentAtRule) => {\n Object.keys(ruleSet).forEach((prop) => {\n let rule = ruleSet[prop];\n if (typeof rule === 'object') {\n if (node.name !== 'media') {\n let extRule = postcss.rule({ selector: unwrapAmp(prop, node) });\n applyRuleSetToNode(rule, extRule);\n\n let globalSelector = getGlobalSelector(node);\n node.parent.insertAfter(ampInsertedNodes[globalSelector] || node, extRule);\n ampInsertedNodes[globalSelector] = extRule;\n } else {\n let mediaNestedRule = postcss.parse(`${prop} ${JSON.stringify(rule).replace(/\"/g, '')}`);\n node.append(mediaNestedRule);\n }\n } else {\n if (currentAtRule) {\n node.insertBefore(currentAtRule, { prop, value: rule });\n } else {\n node.append({ prop, value: rule });\n }\n }\n });\n};\n\nexport default postcss.plugin('postcss-neat', (opts) => {\n options = Object.assign({}, neatCore.variables, opts);\n return (root) => {\n ampInsertedNodes = {};\n root.walkAtRules(/^neat-/i, (rule) => {\n let atRule = rule.name.trim().replace('neat-', '');\n if (atRules[atRule]) {\n let params = rule.params.trim() ? rule.params.trim().split(' ') : [];\n let ruleSet = atRules[atRule](...params);\n applyRuleSetToNode(ruleSet, rule.parent, rule);\n }\n rule.remove();\n });\n };\n});\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postcss-neat", 3 | "version": "2.5.3", 4 | "description": "PostCSS plugin that provides a semantic and fluid grid framework.", 5 | "keywords": [ 6 | "postcss-plugin", 7 | "postcss", 8 | "css", 9 | "postcssplugin", 10 | "columns", 11 | "grid", 12 | "layout", 13 | "media", 14 | "media-queries", 15 | "neat", 16 | "queries", 17 | "semantic" 18 | ], 19 | "author": { 20 | "name": "Alexandr Marinenko", 21 | "url": "http://codepen.io/jo-asakura/popular/" 22 | }, 23 | "homepage": "http://jo-asakura.github.io/postcss-neat/", 24 | "license": "MIT", 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/jo-asakura/postcss-neat.git" 28 | }, 29 | "dependencies": { 30 | "babel-polyfill": "6.7.4", 31 | "postcss": "5.0.19" 32 | }, 33 | "devDependencies": { 34 | "autoprefixer": "6.3.6", 35 | "babel-core": "6.7.4", 36 | "babel-eslint": "6.0.2", 37 | "babel-preset-es2015": "6.6.0", 38 | "chai": "3.5.0", 39 | "clean-css": "3.4.11", 40 | "del": "1.2.0", 41 | "eslint": "0.11.0-alpha.0", 42 | "gulp": "3.9.1", 43 | "gulp-babel": "6.1.2", 44 | "gulp-concat": "2.6.0", 45 | "gulp-eslint": "0.12.0", 46 | "gulp-mocha": "2.2.0", 47 | "gulp-postcss": "6.1.0", 48 | "gulp-sourcemaps": "1.5.2", 49 | "postcss-media-minmax": "2.1.2", 50 | "postcss-nested": "0.3.2", 51 | "postcss-simple-vars": "0.3.0" 52 | }, 53 | "main": "lib/index.js", 54 | "scripts": { 55 | "test": "gulp", 56 | "build": "gulp build", 57 | "prepublish": "npm run build" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/core/functions.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let functions = { 4 | // Convert to percentage 5 | percentage(value = 0) { 6 | value = +value; 7 | return `${value <= 1 ? (value * 100).toFixed(8) : value}%`; 8 | }, 9 | 10 | // Simple clearfix 11 | clearfix() { 12 | return { 13 | '*zoom': 1, 14 | '&:before, &:after': { 15 | 'content': '" "', 16 | 'display': 'table' 17 | }, 18 | '&:after': { 19 | 'clear': 'both' 20 | } 21 | }; 22 | } 23 | }; 24 | 25 | functions = Object.assign(functions, { 26 | // Sets layout direction and layout opposite direction to `@direction` 27 | // and `@opposite-direction` accordingly. 28 | getDirection(layout) { 29 | return { 30 | direction: layout === 'LTR' ? 'right' : 'left', 31 | oppositeDirection: layout === 'LTR' ? 'left' : 'right' 32 | }; 33 | }, 34 | 35 | // Sets neat grid column's width to `@column-width`. 36 | flexWidth(columns, containerColumns, column, gutter) { 37 | columns = +columns; 38 | containerColumns = +containerColumns; 39 | column = +column.replace('em', '').replace('px', ''); 40 | gutter = +gutter.replace('em', '').replace('px', ''); 41 | 42 | var tmpWidth = columns * column + (columns - 1) * gutter; 43 | var tmpContainerWidth = containerColumns * column + (containerColumns - 1) * gutter; 44 | 45 | return tmpWidth / tmpContainerWidth; // columnWidth 46 | }, 47 | 48 | // Sets neat grid column's gutter (the white space between two columns) to `@column-gutter`. 49 | flexGutter(containerColumns, column, gutter) { 50 | containerColumns = +containerColumns; 51 | column = +column.replace('em', '').replace('px', ''); 52 | gutter = +gutter.replace('em', '').replace('px', ''); 53 | 54 | var tmpContainerWidth = containerColumns * column + (containerColumns - 1) * gutter; 55 | 56 | return gutter / tmpContainerWidth; // columnGutter 57 | } 58 | }); 59 | 60 | export default functions; 61 | -------------------------------------------------------------------------------- /src/core/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import functions from './functions.es6.js'; 4 | import variables from './variables.es6.js'; 5 | 6 | export default { 7 | functions, 8 | variables 9 | }; 10 | -------------------------------------------------------------------------------- /src/core/variables.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const locals = { 4 | defaultEmSize: 1, 5 | goldenRatio: 1.618 6 | }; 7 | 8 | let variables = { 9 | // Sets the default display mode. Can be `block`, `table` or `block-collapse`. 10 | neatDefaultDisplay: 'block', 11 | 12 | // Sets the default layout direction of the grid. Can be `LTR` or `RTL`. 13 | neatDefaultDirection: 'LTR', 14 | 15 | // Sets the number of columns the element spans. Its value can be overridden inside a mixin using the `@columns` variable. 16 | neatElementColumns: 1, 17 | 18 | // Sets the total number of columns in the grid. Its value can be overridden inside a mixin using the `@container-columns` variable. 19 | neatGridColumns: 12, 20 | 21 | // Sets the relative width of a single grid column. The unit used should be the same one used to define `@neat-gutter-width`. 22 | neatColumnWidth: (((locals.defaultEmSize * locals.goldenRatio) * locals.goldenRatio) * locals.goldenRatio).toString() + 'em', 23 | 24 | // Sets the relative width of a single grid gutter. The unit used should be the same one used to define `@neat-column-width`. 25 | neatGutterWidth: (locals.defaultEmSize * locals.goldenRatio).toString() + 'em', 26 | 27 | // Sets the max-width property of the element that includes `@neat-outer-container`. 28 | neatMaxWidth: ((1024 / 16) * locals.defaultEmSize).toString() + 'em', 29 | 30 | // Sets the background color for the debugging grid. 31 | debugGridColor: '#ecf0f1', 32 | 33 | // Sets the default location of the debugging grid. 34 | debugGridLocation: 'after' 35 | }; 36 | 37 | export default variables; 38 | -------------------------------------------------------------------------------- /src/grid/fill-parent.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | 5 | // Forces the element to fill its parent container. 6 | // 7 | // @example - PostCSS Usage 8 | // .element { 9 | // @neat-fill-parent; 10 | // } 11 | // 12 | // @example - CSS Output 13 | // .element { 14 | // box-sizing: border-box; 15 | // width: 100%; 16 | // } 17 | // 18 | 19 | let fillParent = (options = variables) => { 20 | return { 21 | 'box-sizing': 'border-box', 22 | 'width': '100%' 23 | }; 24 | }; 25 | 26 | export default fillParent; 27 | -------------------------------------------------------------------------------- /src/grid/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import fillParent from './fill-parent.es6.js'; 4 | import omega from './omega.es6.js'; 5 | import outerContainer from './outer-container.es6.js'; 6 | import pad from './pad.es6.js'; 7 | import row from './row.es6.js'; 8 | import shift from './shift.es6.js'; 9 | import showGrid from './show-grid.es6.js'; 10 | import spanColumns from './span-columns.es6.js'; 11 | 12 | export default { 13 | fillParent, 14 | omega, 15 | outerContainer, 16 | pad, 17 | row, 18 | shift, 19 | showGrid, 20 | spanColumns 21 | }; 22 | -------------------------------------------------------------------------------- /src/grid/omega.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | import functions from '../core/functions.es6.js'; 5 | 6 | // Removes the element's gutter margin, regardless of its position in the grid hierarchy or display property. 7 | // It can target a specific element, or every `nth-child` occurrence. Works only with `block` layouts. 8 | // 9 | // @query 10 | // Supported arguments are `nth-child` selectors (targets a specific pseudo element) and `auto` (targets `last-child`). 11 | // 12 | // When passed an `nth-child` argument of type `*n` with `block` display, the omega mixin automatically 13 | // adds a clear to the `*n+1` th element. 14 | // 15 | // Note that composite arguments such as `2n+1` do not support this feature. 16 | // 17 | // @direction 18 | // Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left). 19 | // 20 | // @example - PostCSS Usage 21 | // .element { 22 | // @neat-omega; 23 | // } 24 | // 25 | // .nth-element { 26 | // @neat-omega 4n; 27 | // } 28 | // 29 | // .auto-element { 30 | // @neat-omega auto; 31 | // } 32 | // 33 | // @example - CSS Output 34 | // .element { 35 | // margin-right: 0; 36 | // } 37 | // 38 | // .nth-element:nth-child(4n) { 39 | // margin-right: 0; 40 | // } 41 | // 42 | // .nth-element:nth-child(4n+1) { 43 | // clear: left; 44 | // } 45 | // 46 | // .auto-element:last-child { 47 | // margin-right: 0; 48 | // } 49 | // 50 | 51 | let omega = (query, direction, options = variables) => { 52 | direction = direction || options.neatDefaultDirection; 53 | 54 | let directions = functions.getDirection(direction); 55 | if (!query) { 56 | return { 57 | [`margin-${directions.direction}`]: 0 58 | }; 59 | } else if (query === 'auto') { 60 | return { 61 | '&:last-child': { 62 | [`margin-${directions.direction}`]: 0 63 | } 64 | }; 65 | } else if (query) { 66 | let result = { 67 | [`&:nth-child(${query})`]: { 68 | [`margin-${directions.direction}`]: 0 69 | } 70 | }; 71 | 72 | if (query.indexOf('n') >= 0) { 73 | result[`&:nth-child(${query} + 1)`] = { 74 | 'clear': directions.oppositeDirection 75 | }; 76 | } 77 | 78 | return result; 79 | } 80 | }; 81 | 82 | export default omega; 83 | -------------------------------------------------------------------------------- /src/grid/outer-container.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | import functions from '../core/functions.es6.js'; 5 | 6 | // Makes an element a outer container by centring it in the viewport, clearing its floats, and setting its `max-width`. 7 | // Although optional, using `outer-container` is recommended. The mixin can be called on more than one element per page, 8 | // as long as they are not nested. 9 | // 10 | // @local-max-width 11 | // Max width to be applied to the element. Can be a percentage or a measure. 12 | // 13 | // @example - PostCSS Usage 14 | // .element { 15 | // @neat-outer-container 100%; 16 | // } 17 | // 18 | // @example - CSS Output 19 | // .element { 20 | // *zoom: 1; 21 | // max-width: 100%; 22 | // margin-left: auto; 23 | // margin-right: auto; 24 | // } 25 | // 26 | // .element:before, 27 | // .element:after { 28 | // content: " "; 29 | // display: table; 30 | // } 31 | // 32 | // .element:after { 33 | // clear: both; 34 | // } 35 | // 36 | 37 | let outerContainer = (maxWidth, options = variables) => { 38 | maxWidth = maxWidth || options.neatMaxWidth; 39 | 40 | return Object.assign({ 41 | 'max-width': maxWidth, 42 | 'margin-left': 'auto', 43 | 'margin-right': 'auto' 44 | }, functions.clearfix()); 45 | }; 46 | 47 | export default outerContainer; 48 | -------------------------------------------------------------------------------- /src/grid/pad.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | import functions from '../core/functions.es6.js'; 5 | 6 | // Adds padding to the element. 7 | // 8 | // @padding 9 | // A list of padding value(s) to use. Passing `default` in the list will result 10 | // in using the gutter width as a padding value. 11 | // 12 | // @example - PostCSS Usage 13 | // .element { 14 | // @neat-pad 30px -20px 10px default; 15 | // } 16 | // 17 | // @example - CSS Output 18 | // .element { 19 | // padding: 30px -20px 10px 2.3576516%; 20 | // } 21 | // 22 | 23 | let pad = (padding = 'default', options = variables) => { 24 | let columnGutter = functions.percentage(functions.flexGutter(options.neatGridColumns, options.neatColumnWidth, options.neatGutterWidth)); 25 | let parts = Array.isArray(padding) ? padding : padding.split(' '); 26 | 27 | if (!parts.length) { 28 | parts.push('default'); 29 | } 30 | 31 | return { 32 | 'padding': parts.reduce((aggr, value) => { 33 | aggr.push(value === 'default' ? columnGutter : value); 34 | return aggr; 35 | }, []).join(' ') 36 | }; 37 | }; 38 | 39 | export default pad; 40 | -------------------------------------------------------------------------------- /src/grid/row.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | import functions from '../core/functions.es6.js'; 5 | import fillParent from './fill-parent.es6.js'; 6 | 7 | // Designates the element as a row of columns in the grid layout. It clears the floats on the element and 8 | // sets its display property. Rows can't be nested, but there can be more than one row element 9 | // with different display properties per layout. 10 | // 11 | // @display 12 | // Sets the display property of the element and the display context that 13 | // will be used by its children. Can be `block` or `table`. 14 | // 15 | // @direction 16 | // Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left). 17 | // 18 | // @example - PostCSS Usage 19 | // .element { 20 | // @neat-row; 21 | // } 22 | // 23 | // @example - CSS Output 24 | // .element { 25 | // *zoom: 1; 26 | // display: block; 27 | // } 28 | // 29 | // .element:before, 30 | // .element:after { 31 | // content: " "; 32 | // display: table; 33 | // } 34 | // 35 | // .element:after { 36 | // clear: both; 37 | // } 38 | // 39 | 40 | let row = (display, options = variables) => { 41 | display = display || options.neatDefaultDisplay; 42 | 43 | if (display === 'table') { 44 | return Object.assign({ 45 | 'display': 'table', 46 | 'table-layout': 'fixed' 47 | }, fillParent()); 48 | } else { 49 | return Object.assign({ 50 | 'display': 'block' 51 | }, functions.clearfix()); 52 | } 53 | }; 54 | 55 | export default row; 56 | -------------------------------------------------------------------------------- /src/grid/shift.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | import functions from '../core/functions.es6.js'; 5 | 6 | // Translates an element horizontally by a number of columns, in a specific nesting context. 7 | // 8 | // @columns 9 | // The number of columns to shift (required). 10 | // 11 | // @container-columns 12 | // The number of columns of the parent element. 13 | // 14 | // @direction 15 | // Sets the layout direction. Can be `LTR` (left-to-right) or `RTL` (right-to-left). 16 | // 17 | // @example - PostCSS Usage 18 | // .element-neg { 19 | // @neat-shift -3 6; 20 | // } 21 | // 22 | // .element-pos { 23 | // @neat-shift 2; 24 | // } 25 | // 26 | // @example - CSS output 27 | // .element-neg { 28 | // margin-left: -52.41457896%; 29 | // } 30 | // 31 | // .element-pos { 32 | // margin-left: 17.0596086%; 33 | // } 34 | // 35 | 36 | let shift = (columns, containerColumns, direction, options = variables) => { 37 | containerColumns = containerColumns || options.neatGridColumns; 38 | direction = direction || options.neatDefaultDirection; 39 | 40 | let directions = functions.getDirection(direction); 41 | let columnWidth = functions.flexWidth(1, containerColumns, options.neatColumnWidth, options.neatGutterWidth); 42 | let columnGutter = functions.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth); 43 | return { 44 | [`margin-${directions.oppositeDirection}`]: functions.percentage(columns * columnWidth + columns * columnGutter) 45 | }; 46 | }; 47 | 48 | export default shift; 49 | -------------------------------------------------------------------------------- /src/grid/show-grid.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | import functions from '../core/functions.es6.js'; 5 | 6 | // Creates a debugging grid for the parent of columns. Works in conjunction with `@neat-outer-container`. 7 | // 8 | // @columns 9 | // The unitless number of columns the element spans. If is not passed, it is equal to `@neatElementColumns`. 10 | // `@columns` also accepts decimals for when it's necessary to break out of the standard grid. 11 | // E.g. Passing `2.4` in a standard 12 column grid will divide the row into 5 columns. 12 | // 13 | // @container-columns 14 | // The number of columns the parent element spans. If is not passed, it is equal to `@neatGridColumns`, 15 | // the total number of columns in the grid. 16 | // 17 | // @location 18 | // The location of where the grid will be applied to: ['before', 'after' or 'background'] 19 | // 20 | // @example - PostCSS Usage 21 | // .element { 22 | // @neat-outer-container; 23 | // @neat-show-grid 4 12; 24 | // } 25 | // 26 | // @example - CSS Output 27 | // .element { 28 | // *zoom: 1; 29 | // max-width: 128em; 30 | // margin-left: auto; 31 | // margin-right: auto; 32 | // } 33 | // .element:before, 34 | // .element:after { 35 | // content: " "; 36 | // display: table; 37 | // } 38 | // .element:after { 39 | // clear: both; 40 | // background: linear-gradient(to right, 41 | // #ecf0f1 0, #ecf0f1 31.7615656%, 42 | // transparent 31.7615656%, transparent 34.1192172%, 43 | // #ecf0f1 34.1192172%, #ecf0f1 65.88078280%, 44 | // transparent 65.88078280%, transparent 68.2384344%, 45 | // #ecf0f1 68.2384344%, #ecf0f1 100%); 46 | // bottom: 0; 47 | // display: block; 48 | // left: 0; 49 | // position: absolute; 50 | // right: 0; 51 | // top: 0 52 | // } 53 | // 54 | 55 | const generateArray = (length = 0) => { 56 | return Array.from(new Array(length), (x, i) => i); 57 | }; 58 | 59 | let showGrid = (columns, containerColumns, location, direction, options = variables) => { 60 | columns = columns || options.neatElementColumns; 61 | containerColumns = containerColumns || options.neatGridColumns; 62 | location = location || options.debugGridLocation; 63 | direction = direction || options.neatDefaultDirection; 64 | 65 | let columnsCount = +(containerColumns / columns); 66 | let directions = functions.getDirection(direction); 67 | let columnWidth = functions.flexWidth(columns, containerColumns, options.neatColumnWidth, options.neatGutterWidth); 68 | let columnGutter = functions.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth); 69 | 70 | let gradient = generateArray(columnsCount).reduce((memo, idx) => { 71 | let startColor = columnWidth * idx + columnGutter * idx; 72 | let endColor = columnWidth * (idx + 1) + columnGutter * idx; 73 | let startBlank = endColor; 74 | let endBlank = columnWidth * (idx + 1) + columnGutter * (idx + 1); 75 | memo.push(`${options.debugGridColor} ${functions.percentage(startColor)}, ${options.debugGridColor} ${functions.percentage(endColor)}`); 76 | if (idx < columnsCount - 1) { 77 | memo.push(`transparent ${functions.percentage(startBlank)}, transparent ${functions.percentage(endBlank)}`); 78 | } 79 | return memo; 80 | }, [directions.direction === 'right' ? 'to right' : 'to left']); 81 | 82 | // 'before', 'after' or 'background' 83 | if (location === 'background') { 84 | return { 85 | 'background': `linear-gradient(${gradient.join(',')})` 86 | }; 87 | } else if (location === 'before' || location === 'after') { 88 | return { 89 | [`&:${location}`]: { 90 | 'background': `linear-gradient(${gradient.join(',')})`, 91 | 'bottom': '0', 92 | 'display': 'block', 93 | 'left': '0', 94 | 'position': 'absolute', 95 | 'right': '0', 96 | 'top': '0' 97 | } 98 | }; 99 | } 100 | }; 101 | 102 | export default showGrid; 103 | -------------------------------------------------------------------------------- /src/grid/span-columns.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import variables from '../core/variables.es6.js'; 4 | import functions from '../core/functions.es6.js'; 5 | 6 | // Specifies the number of columns an element should span. If the selector is nested the number of columns 7 | // of its parent element should be passed as an argument as well. 8 | // 9 | // @columns 10 | // The unitless number of columns the element spans. If is not passed, it is equal to `@neatElementColumns`. 11 | // `@columns` also accepts decimals for when it's necessary to break out of the standard grid. 12 | // E.g. Passing `2.4` in a standard 12 column grid will divide the row into 5 columns. 13 | // 14 | // @container-columns 15 | // The number of columns the parent element spans. If is not passed, it is equal to `@neatGridColumns`, 16 | // the total number of columns in the grid. 17 | // 18 | // @display 19 | // Sets the display property of the element. By default it sets the display property of the element to `block`. 20 | // If passed `block-collapse`, it also removes the margin gutter by adding it to the element width. 21 | // If passed `table`, it sets the display property to `table-cell` and calculates the width of the 22 | // element without taking gutters into consideration. The result does not align with the block-based grid. 23 | // 24 | // @example - PostCSS Usage 25 | // .element { 26 | // @neat-span-columns 6; 27 | // 28 | // .nested-element { 29 | // @neat-span-columns 2 6; 30 | // } 31 | // } 32 | // 33 | // @example - CSS Output 34 | // .element { 35 | // display: block; 36 | // float: left; 37 | // margin-right: 2.3576516%; 38 | // width: 48.8211742%; 39 | // } 40 | // 41 | // .element:last-child { 42 | // margin-right: 0; 43 | // } 44 | // 45 | // .element .nested-element { 46 | // display: block; 47 | // float: left; 48 | // margin-right: 4.82915791%; 49 | // width: 30.11389472%; 50 | // } 51 | // 52 | // .element .nested-element:last-child { 53 | // margin-right: 0; 54 | // } 55 | // 56 | 57 | let spanColumns = (columns, containerColumns, display, direction, options = variables) => { 58 | columns = columns || options.neatElementColumns; 59 | containerColumns = containerColumns || options.neatGridColumns; 60 | display = display || options.neatDefaultDisplay; 61 | direction = direction || options.neatDefaultDirection; 62 | 63 | let directions = functions.getDirection(direction); 64 | let columnWidth = functions.flexWidth(columns, containerColumns, options.neatColumnWidth, options.neatGutterWidth); 65 | let columnGutter = functions.flexGutter(containerColumns, options.neatColumnWidth, options.neatGutterWidth); 66 | 67 | if (display === 'table') { 68 | return { 69 | 'display': 'table-cell', 70 | 'width': functions.percentage(columns / containerColumns) 71 | }; 72 | } else if (display === 'block-collapse') { 73 | return { 74 | 'display': 'block', 75 | 'float': directions.oppositeDirection, 76 | 'width': functions.percentage(columnWidth + columnGutter), 77 | // --- 78 | '&:last-child': { 79 | 'width': functions.percentage(columnWidth) 80 | } 81 | }; 82 | } else { 83 | return { 84 | 'display': 'block', 85 | 'float': directions.oppositeDirection, 86 | [`margin-${directions.direction}`]: functions.percentage(columnGutter), 87 | 'width': functions.percentage(columnWidth), 88 | // --- 89 | '&:last-child': { 90 | [`margin-${directions.direction}`]: 0 91 | } 92 | }; 93 | } 94 | }; 95 | 96 | export default spanColumns; 97 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('babel-polyfill'); 4 | module.exports = require('./neat-parser.js').default; 5 | -------------------------------------------------------------------------------- /src/neat-parser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('babel-polyfill'); 4 | 5 | import postcss from 'postcss'; 6 | import neatCore from './core'; 7 | import neatGrid from './grid'; 8 | 9 | let options = {}; 10 | let ampInsertedNodes = {}; 11 | 12 | const atRules = { 13 | 'fill-parent' () { 14 | return neatGrid.fillParent(options); 15 | }, 16 | 'omega' (query, direction) { 17 | return neatGrid.omega(query, direction, options); 18 | }, 19 | 'outer-container' (maxWidth) { 20 | return neatGrid.outerContainer(maxWidth, options); 21 | }, 22 | 'pad' (...padding) { 23 | return neatGrid.pad(padding, options); 24 | }, 25 | 'row' (display) { 26 | return neatGrid.row(display, options); 27 | }, 28 | 'shift' (columns, containerColumns, direction) { 29 | return neatGrid.shift(columns, containerColumns, direction, options); 30 | }, 31 | 'show-grid' (columns, containerColumns, location, direction) { 32 | return neatGrid.showGrid(columns, containerColumns, location, direction, options); 33 | }, 34 | 'span-columns' (columns, containerColumns, display, direction) { 35 | return neatGrid.spanColumns(columns, containerColumns, display, direction, options); 36 | } 37 | }; 38 | 39 | const unwrapAmp = (nodeSelector, node) => { 40 | if (nodeSelector.indexOf('&:') >= 0 && node.name !== 'media') { 41 | return node.selectors.map((selector) => { 42 | return nodeSelector.replace(/&/g, selector); 43 | }).join(','); 44 | } 45 | return nodeSelector; 46 | }; 47 | 48 | const getGlobalSelector = (node) => { 49 | if (node.parent && node.parent.type === 'atrule') { 50 | return `${node.parent.name} ${node.parent.params} ${node.selector}`; 51 | } else if (node.name === 'media') { 52 | return getGlobalSelector(node.parent); 53 | } 54 | return node.selector; 55 | }; 56 | 57 | const applyRuleSetToNode = (ruleSet, node, currentAtRule) => { 58 | Object.keys(ruleSet).forEach((prop) => { 59 | let rule = ruleSet[prop]; 60 | if (typeof rule === 'object') { 61 | if (node.name !== 'media') { 62 | let extRule = postcss.rule({ selector: unwrapAmp(prop, node) }); 63 | applyRuleSetToNode(rule, extRule); 64 | 65 | let globalSelector = getGlobalSelector(node); 66 | node.parent.insertAfter(ampInsertedNodes[globalSelector] || node, extRule); 67 | ampInsertedNodes[globalSelector] = extRule; 68 | } else { 69 | let mediaNestedRule = postcss.parse(`${prop} ${JSON.stringify(rule).replace(/"/g, '')}`); 70 | node.append(mediaNestedRule); 71 | } 72 | } else { 73 | if (currentAtRule) { 74 | node.insertBefore(currentAtRule, { prop, value: rule }); 75 | } else { 76 | node.append({ prop, value: rule }); 77 | } 78 | } 79 | }); 80 | }; 81 | 82 | export default postcss.plugin('postcss-neat', (opts) => { 83 | options = Object.assign({}, neatCore.variables, opts); 84 | return (root) => { 85 | ampInsertedNodes = {}; 86 | root.walkAtRules(/^neat-/i, (rule) => { 87 | let atRule = rule.name.trim().replace('neat-', ''); 88 | if (atRules[atRule]) { 89 | let params = rule.params.trim() ? rule.params.trim().split(' ') : []; 90 | let ruleSet = atRules[atRule](...params); 91 | applyRuleSetToNode(ruleSet, rule.parent, rule); 92 | } 93 | rule.remove(); 94 | }); 95 | }; 96 | }); 97 | -------------------------------------------------------------------------------- /test/test.es6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import chai from 'chai'; 4 | let expect = chai.expect; 5 | 6 | import neatCore from '../src/core'; 7 | import neatGrid from '../src/grid'; 8 | 9 | import postcss from 'postcss'; 10 | import postcssNeat from '../src/index.js'; 11 | 12 | import CleanCss from 'clean-css'; 13 | let minifier = new CleanCss(); 14 | let cleanCss = (css) => minifier.minify(css || '').styles; 15 | 16 | let test = (input, output, done, options = {}) => { 17 | postcss([postcssNeat(options)]).process(input) 18 | .then((result) => { 19 | // console.info('RESULT (expected):\n', output); 20 | // console.info('RESULT:\n', result.css); 21 | // console.info('-----'); 22 | expect(cleanCss(result.css)).to.eql(cleanCss(output)); 23 | expect(result.warnings()).to.be.empty; 24 | done(); 25 | }) 26 | .catch((error) => { 27 | done(error); 28 | }); 29 | }; 30 | 31 | describe('postcss-neat::usage', function () { 32 | it('1. `fill-parent` should render proper rule-set', function (done) { 33 | test( 34 | `.element { 35 | @neat-fill-parent; 36 | }`, 37 | `.element { 38 | box-sizing: border-box; 39 | width: 100%; 40 | }`, 41 | done); 42 | }); 43 | 44 | it('2. `omega` should render proper rule-set', function (done) { 45 | test( 46 | `.element { 47 | @neat-omega; 48 | }`, 49 | `.element { 50 | margin-right: 0; 51 | }`, 52 | done); 53 | }); 54 | 55 | it('3. `omega 4n` should render proper rule-set', function (done) { 56 | test( 57 | `.nth-element { 58 | @neat-omega 4n; 59 | }`, 60 | `.nth-element:nth-child(4n) { 61 | margin-right: 0; 62 | } 63 | 64 | .nth-element:nth-child(4n+1) { 65 | clear: left; 66 | }`, 67 | done); 68 | }); 69 | 70 | it('4. `omega auto` should render proper rule-set', function (done) { 71 | test( 72 | `.auto-element { 73 | @neat-omega auto; 74 | }`, 75 | `.auto-element:last-child { 76 | margin-right: 0; 77 | }`, 78 | done); 79 | }); 80 | 81 | it('5. `outer-container 100%` should render proper rule-set', function (done) { 82 | test( 83 | `.element { 84 | @neat-outer-container 100%; 85 | }`, 86 | `.element { 87 | *zoom: 1; 88 | max-width: 100%; 89 | margin-left: auto; 90 | margin-right: auto; 91 | } 92 | 93 | .element:before, 94 | .element:after { 95 | content: " "; 96 | display: table; 97 | } 98 | 99 | .element:after { 100 | clear: both; 101 | }`, 102 | done); 103 | }); 104 | 105 | it('6. `pad 30px -20px 10px default` should render proper rule-set', function (done) { 106 | test( 107 | `.element { 108 | @neat-pad 30px -20px 10px default; 109 | }`, 110 | `.element { 111 | padding: 30px -20px 10px 2.3576516%; 112 | }`, 113 | done); 114 | }); 115 | 116 | it('7. `pad` should render proper rule-set', function (done) { 117 | test( 118 | `.element { 119 | @neat-pad; 120 | }`, 121 | `.element { 122 | padding: 2.3576516%; 123 | }`, 124 | done); 125 | }); 126 | 127 | it('8. `row` should render proper rule-set', function (done) { 128 | test( 129 | `.element { 130 | @neat-row; 131 | }`, 132 | `.element { 133 | *zoom: 1; 134 | display: block; 135 | } 136 | 137 | .element:before, 138 | .element:after { 139 | content: " "; 140 | display: table; 141 | } 142 | 143 | .element:after { 144 | clear: both; 145 | }`, 146 | done); 147 | }); 148 | 149 | it('9. `row table` should render proper rule-set', function (done) { 150 | test( 151 | `.element { 152 | @neat-row table; 153 | }`, 154 | `.element { 155 | display: table; 156 | table-layout: fixed; 157 | box-sizing: border-box; 158 | width: 100%; 159 | }`, 160 | done); 161 | }); 162 | 163 | it('10. `shift -3 6` should render proper rule-set', function (done) { 164 | test( 165 | `.element-neg { 166 | @neat-shift -3 6; 167 | }`, 168 | `.element-neg { 169 | margin-left: -52.41457896%; 170 | }`, 171 | done); 172 | }); 173 | 174 | it('11. `shift 2` should render proper rule-set', function (done) { 175 | test( 176 | `.element-pos { 177 | @neat-shift 2; 178 | }`, 179 | `.element-pos { 180 | margin-left: 17.05960860%; 181 | }`, 182 | done); 183 | }); 184 | 185 | it('12. `shift 4 12 RTL` should render proper rule-set', function (done) { 186 | test( 187 | `.element-pos { 188 | @neat-shift 4 12 RTL; 189 | }`, 190 | `.element-pos { 191 | margin-right: 34.1192172%; 192 | }`, 193 | done); 194 | }); 195 | 196 | it('13. `shift 4 12 RTL` should render proper rule-set', function (done) { 197 | test( 198 | `.element-pos { 199 | @neat-shift 4 12 RTL; 200 | }`, 201 | `.element-pos { 202 | margin-right: 34.1192172%; 203 | }`, 204 | done); 205 | }); 206 | 207 | it('14. `span-columns 6` should render proper rule-set', function (done) { 208 | test( 209 | `.element { 210 | @neat-span-columns 6; 211 | }`, 212 | `.element { 213 | display: block; 214 | float: left; 215 | margin-right: 2.3576516%; 216 | width: 48.8211742%; 217 | } 218 | 219 | .element:last-child { 220 | margin-right: 0; 221 | }`, 222 | done); 223 | }); 224 | 225 | it('15. `span-columns 2 6` should render proper rule-set', function (done) { 226 | test( 227 | `.element .nested-element { 228 | @neat-span-columns 2 6; 229 | }`, 230 | `.element .nested-element { 231 | display: block; 232 | float: left; 233 | margin-right: 4.82915791%; 234 | width: 30.11389472%; 235 | } 236 | 237 | .element .nested-element:last-child { 238 | margin-right: 0; 239 | }`, 240 | done); 241 | }); 242 | 243 | it('16. `outer-container` and custom `neatMaxWidth` should render proper rule-set', function (done) { 244 | test( 245 | `.element { 246 | @neat-outer-container; 247 | }`, 248 | `.element { 249 | *zoom: 1; 250 | max-width: 128em; 251 | margin-left: auto; 252 | margin-right: auto; 253 | } 254 | 255 | .element:before, 256 | .element:after { 257 | content: " "; 258 | display: table; 259 | } 260 | 261 | .element:after { 262 | clear: both; 263 | }`, 264 | done, { 265 | neatMaxWidth: '128em' 266 | }); 267 | }); 268 | 269 | it('17. `span-columns 12` and custom `neatGutterWidth` should render proper rule-set', function (done) { 270 | let columns = 12; 271 | 272 | let options = Object.assign({}, neatCore.variables); 273 | options.neatGutterWidth = '20em'; 274 | 275 | let flexGutter = neatCore.functions.flexGutter(options.neatGridColumns, options.neatColumnWidth, options.neatGutterWidth); 276 | let flexWidth = neatCore.functions.flexWidth(columns, options.neatGridColumns, options.neatColumnWidth, options.neatGutterWidth); 277 | 278 | test( 279 | `.element { 280 | @neat-span-columns ${columns}; 281 | }`, 282 | `.element { 283 | display: block; 284 | float: left; 285 | margin-right: ${neatCore.functions.percentage(flexGutter)}; 286 | width: ${neatCore.functions.percentage(flexWidth)}; 287 | } 288 | 289 | .element:last-child { 290 | margin-right: 0; 291 | }`, 292 | done, { 293 | neatGutterWidth: options.neatGutterWidth 294 | }); 295 | }); 296 | 297 | it('18. `span-columns 6` and custom `neatGridColumns` should render proper rule-set', function (done) { 298 | test( 299 | `.element { 300 | @neat-span-columns 6; 301 | }`, 302 | `.element { 303 | display: block; 304 | float: left; 305 | margin-right: 4.82915791%; 306 | width: 100%; 307 | } 308 | 309 | .element:last-child { 310 | margin-right: 0; 311 | }`, 312 | done, { 313 | neatGridColumns: 6 314 | }); 315 | }); 316 | 317 | it('19. `show-grid` in conjunction with `outer-container` should render proper rule-set', function (done) { 318 | test( 319 | `.element { 320 | @neat-outer-container; 321 | @neat-show-grid 4 12; 322 | }`, 323 | `.element { 324 | *zoom: 1; 325 | max-width: 128em; 326 | margin-left: auto; 327 | margin-right: auto; 328 | } 329 | .element:before, 330 | .element:after { 331 | content: " "; 332 | display: table; 333 | } 334 | .element:after { 335 | clear: both; 336 | background: linear-gradient(to right, 337 | #ecf0f1 0, #ecf0f1 31.7615656%, 338 | transparent 31.7615656%, transparent 34.1192172%, 339 | #ecf0f1 34.1192172%, #ecf0f1 65.88078280%, 340 | transparent 65.88078280%, transparent 68.2384344%, 341 | #ecf0f1 68.2384344%, #ecf0f1 100%); 342 | bottom: 0; 343 | display: block; 344 | left: 0; 345 | position: absolute; 346 | right: 0; 347 | top: 0 348 | }`, 349 | done, { 350 | neatMaxWidth: '128em' 351 | }); 352 | }); 353 | 354 | it('20. `show-grid` in conjunction with `outer-container` should render proper rule-set', function (done) { 355 | test( 356 | `.element { 357 | @neat-outer-container; 358 | @neat-show-grid 4 12 background; 359 | }`, 360 | `.element { 361 | *zoom: 1; 362 | max-width: 128em; 363 | margin-left: auto; 364 | margin-right: auto; 365 | background: linear-gradient(to right, 366 | #ecf0f1 0, #ecf0f1 31.7615656%, 367 | transparent 31.7615656%, transparent 34.1192172%, 368 | #ecf0f1 34.1192172%, #ecf0f1 65.88078280%, 369 | transparent 65.88078280%, transparent 68.2384344%, 370 | #ecf0f1 68.2384344%, #ecf0f1 100%); 371 | } 372 | .element:before, 373 | .element:after { 374 | content: " "; 375 | display: table; 376 | } 377 | .element:after { 378 | clear: both; 379 | }`, 380 | done, { 381 | neatMaxWidth: '128em' 382 | }); 383 | }); 384 | 385 | it('21. `span-columns` inside of @media should render proper rule-set', function (done) { 386 | test( 387 | `.parentElement { 388 | .childElement { 389 | @media (max-width: 900px) { 390 | @neat-span-columns 9; 391 | } 392 | } 393 | }`, 394 | `.parentElement { 395 | .childElement { 396 | @media (max-width: 900px) { 397 | display: block; 398 | float: left; 399 | margin-right: 2.35765160%; 400 | width: 74.41058710%; 401 | &:last-child { 402 | margin-right: 0 403 | } 404 | } 405 | } 406 | }`, 407 | done); 408 | }); 409 | 410 | it('22. Ensures that output CSS is in proper order', function (done) { 411 | test( 412 | `.element { 413 | @neat-span-columns 8; 414 | @neat-shift 2; 415 | float: none; 416 | }`, 417 | `.element { 418 | display: block; 419 | float: left; 420 | margin-right: 2.35765160%; 421 | width: 65.88078280%; 422 | margin-left: 17.05960860%; 423 | float: none; 424 | } 425 | .element:last-child { 426 | margin-right: 0; 427 | }`, 428 | done); 429 | }); 430 | }); 431 | 432 | describe('postcss-neat::core', function () { 433 | it('1. functions.percentage should return % of input value', function (done) { 434 | expect(neatCore.functions.percentage(10)).to.eql('10%'); 435 | expect(neatCore.functions.percentage(.1)).to.eql('10.00000000%'); 436 | expect(neatCore.functions.percentage(.25)).to.eql('25.00000000%'); 437 | expect(neatCore.functions.percentage(.99)).to.eql('99.00000000%'); 438 | expect(neatCore.functions.percentage(.125)).to.eql('12.50000000%'); 439 | expect(neatCore.functions.percentage(0)).to.eql('0.00000000%'); 440 | done(); 441 | }); 442 | 443 | it('2. functions.getDirection should return both direction and opposite direction', function (done) { 444 | expect(neatCore.functions.getDirection('LTR')).to.eql({ 445 | direction: 'right', 446 | oppositeDirection: 'left' 447 | }); 448 | expect(neatCore.functions.getDirection('RTL')).to.eql({ 449 | direction: 'left', 450 | oppositeDirection: 'right' 451 | }); 452 | done(); 453 | }); 454 | 455 | it('3. functions.flexWidth should return correct column\'s width', function (done) { 456 | let funcs = neatCore.functions; 457 | let options = neatCore.variables; 458 | expect(funcs.percentage(funcs.flexWidth(6, 12, options.neatColumnWidth, options.neatGutterWidth))).to.eql('48.82117420%'); 459 | expect(funcs.percentage(funcs.flexWidth(2, 6, options.neatColumnWidth, options.neatGutterWidth))).to.eql('30.11389472%'); 460 | expect(funcs.percentage(funcs.flexWidth(1, 12, options.neatColumnWidth, options.neatGutterWidth))).to.eql('6.17215270%'); 461 | done(); 462 | }); 463 | 464 | it('4. functions.flexGutter should return correct column\'s gutter', function (done) { 465 | let funcs = neatCore.functions; 466 | let options = neatCore.variables; 467 | expect(funcs.percentage(funcs.flexGutter(12, options.neatColumnWidth, options.neatGutterWidth))).to.eql('2.35765160%'); 468 | expect(funcs.percentage(funcs.flexGutter(6, options.neatColumnWidth, options.neatGutterWidth))).to.eql('4.82915791%'); 469 | done(); 470 | }); 471 | 472 | it('5. fillParent should return proper rule-set', function (done) { 473 | expect(neatGrid.fillParent()).to.eql({ 474 | 'box-sizing': 'border-box', 475 | 'width': '100%' 476 | }); 477 | done(); 478 | }); 479 | 480 | it('6. omega should return proper rule-set', function (done) { 481 | expect(neatGrid.omega()).to.eql({ 482 | 'margin-right': 0 483 | }); 484 | expect(neatGrid.omega('4n')).to.eql({ 485 | '&:nth-child(4n)': { 486 | 'margin-right': 0 487 | }, 488 | '&:nth-child(4n + 1)': { 489 | 'clear': 'left' 490 | } 491 | }); 492 | expect(neatGrid.omega('auto')).to.eql({ 493 | '&:last-child': { 494 | 'margin-right': 0 495 | } 496 | }); 497 | done(); 498 | }); 499 | 500 | it('7. outerContainer should return proper rule-set', function (done) { 501 | expect(neatGrid.outerContainer('100%')).to.eql({ 502 | 'max-width': '100%', 503 | 'margin-left': 'auto', 504 | 'margin-right': 'auto', 505 | '*zoom': 1, 506 | '&:after': { 507 | 'clear': 'both' 508 | }, 509 | '&:before, &:after': { 510 | 'content': '" "', 511 | 'display': 'table' 512 | } 513 | }); 514 | done(); 515 | }); 516 | 517 | it('8. pad should return proper rule-set', function (done) { 518 | expect(neatGrid.pad('30px -20px 10px default')).to.eql({ 519 | 'padding': '30px -20px 10px 2.35765160%' 520 | }); 521 | done(); 522 | }); 523 | 524 | it('9. row should return proper rule-set', function (done) { 525 | expect(neatGrid.row()).to.eql({ 526 | '*zoom': 1, 527 | 'display': 'block', 528 | '&:before, &:after': { 529 | 'content': '" "', 530 | 'display': 'table' 531 | }, 532 | '&:after': { 533 | 'clear': 'both' 534 | } 535 | }); 536 | done(); 537 | }); 538 | 539 | it('10. shift should return proper rule-set', function (done) { 540 | expect(neatGrid.shift(-3, 6)).to.eql({ 541 | 'margin-left': '-52.41457896%' 542 | }); 543 | expect(neatGrid.shift(2)).to.eql({ 544 | 'margin-left': '17.05960860%' 545 | }); 546 | done(); 547 | }); 548 | 549 | it('11. spanColumns should return proper rule-set', function (done) { 550 | expect(neatGrid.spanColumns(6)).to.eql({ 551 | 'display': 'block', 552 | 'float': 'left', 553 | 'margin-right': '2.35765160%', 554 | 'width': '48.82117420%', 555 | 556 | '&:last-child': { 557 | 'margin-right': 0 558 | } 559 | }); 560 | 561 | expect(neatGrid.spanColumns(9)).to.eql({ 562 | 'display': 'block', 563 | 'float': 'left', 564 | 'margin-right': '2.35765160%', 565 | 'width': '74.41058710%', 566 | 567 | '&:last-child': { 568 | 'margin-right': 0 569 | } 570 | }); 571 | 572 | expect(neatGrid.spanColumns(2, 6)).to.eql({ 573 | 'display': 'block', 574 | 'float': 'left', 575 | 'margin-right': '4.82915791%', 576 | 'width': '30.11389472%', 577 | 578 | '&:last-child': { 579 | 'margin-right': 0 580 | } 581 | }); 582 | 583 | expect(neatGrid.spanColumns(3, 9, 'block-collapse')).to.eql({ 584 | 'display': 'block', 585 | 'float': 'left', 586 | 'width': '34.38947856%', 587 | 588 | '&:last-child': { 589 | 'width': '31.22104287%' 590 | } 591 | }); 592 | 593 | expect(neatGrid.spanColumns(2, 12, 'table')).to.eql({ 594 | 'display': 'table-cell', 595 | 'width': neatCore.functions.percentage(2 / 12) 596 | }); 597 | 598 | done(); 599 | }); 600 | }); 601 | --------------------------------------------------------------------------------