├── .editorconfig ├── .gitignore ├── .jscsrc ├── LICENSE.md ├── README.md ├── index.js ├── package.json └── src └── flex.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [**.{html,js,css,scss,sass,less,jsx,json,xml,yml,sh,rb,md}] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "airbnb", 3 | "esnext": true, 4 | "validateQuoteMarks": null, 5 | "requirePaddingNewLinesAfterBlocks": null, 6 | "disallowMultipleVarDecl": null, 7 | "excludeFiles": [ 8 | "node_modules/**" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Brian Holt 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Work in progress. 2 | 3 | Idea is that you put `display: flex` and this plugin will polyfill it correctly so it will use flex in new browsers and tables in old browsers. 4 | 5 | No tests yet. Not passing lint. Those are forthcoming. Way too many `console.log`s in the code. No good error handling. Massive refactor still to come (the code sucks.) 6 | 7 | IE this code is production ready. :joy: 8 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var helpers = require("postcss-message-helpers"); 2 | var postCss = require('postcss'); 3 | var flex = require('./src/flex'); 4 | 5 | module.exports = postCss.plugin('flex', function plugin(opts) { 6 | return function(style) { 7 | 8 | style.eachAtRule(function(rule) { 9 | console.log('atrule', rule); 10 | }); 11 | 12 | style.eachRule(function transformRule(rule) { 13 | var continueProcessing = true; 14 | var processed; 15 | rule.eachDecl(function transformDecl(decl) { 16 | helpers.try(function helperTry() { 17 | if (decl.prop === 'display' && decl.value === 'flex' && continueProcessing) { 18 | processed = flex.process(decl.parent); 19 | continueProcessing = false; 20 | } 21 | }, decl.source); 22 | }); 23 | if (processed) { 24 | console.log(rule.selector); 25 | if (processed.rule.length) { 26 | rule.nodes = processed.rule; 27 | // rule.removeAll(); 28 | // processed.rule.map(function(decl) { 29 | // rule.append(decl); 30 | // }); 31 | } 32 | 33 | if (processed.atRule.length) { 34 | var newAtInsideRule = postCss.rule({ 35 | nodes: processed.atRule, 36 | selector: rule.selector 37 | }); 38 | 39 | // console.log('newone', newAtInsideRule); 40 | 41 | var newAtOutsideRule = postCss.atRule({ 42 | nodes: [newAtInsideRule], 43 | name: 'supports', 44 | before: rule.before, 45 | after: rule.after, 46 | between: rule.between, 47 | params: '(display: flex)' 48 | }); 49 | 50 | console.log('newatrule', newAtOutsideRule); 51 | 52 | newAtOutsideRule.moveAfter(rule); 53 | } 54 | 55 | if (processed.childRule.length) { 56 | var childRule = rule.cloneAfter({ 57 | nodes:processed.childRule, 58 | selector: rule.selector + " > *" 59 | }); 60 | 61 | // childRule.moveAfter(rule); 62 | } 63 | 64 | } 65 | else { 66 | console.log('lol no'); 67 | } 68 | }); 69 | }; 70 | }); 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postcss-flex", 3 | "version": "0.0.1", 4 | "description": "PostCSS plugin so you can freely write display: flex code and have it work on IE8", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/btholt/postcss-flex.git" 12 | }, 13 | "keywords": [ 14 | "postcss", 15 | "postcssplugin", 16 | "postcss-plugin", 17 | "css", 18 | "flex", 19 | "flexbox" 20 | ], 21 | "author": "Brian Holt ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/btholt/postcss-flex/issues" 25 | }, 26 | "homepage": "https://github.com/btholt/postcss-flex#readme", 27 | "dependencies": { 28 | "postcss": "^4.1.11", 29 | "postcss-message-helpers": "^2.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/flex.js: -------------------------------------------------------------------------------- 1 | var postCss = require('postcss'); 2 | 3 | module.exports = { 4 | process: function(parent) { 5 | if (!parent) { 6 | return {atRule:[],rule:[],childRule:[]}; 7 | } 8 | 9 | var atRule = []; 10 | var newRule = []; 11 | var childRule = [ 12 | postCss.decl({prop:'display', value: 'inline-block'}) 13 | ]; 14 | 15 | console.log(parent === undefined); 16 | parent.eachDecl(function declFlexTransform(decl) { 17 | switch (decl.prop) { 18 | case 'display': 19 | console.log('display'); 20 | atRule.push(postCss.decl({prop: 'display', value:'flex'})); 21 | newRule.push(postCss.decl({prop: 'display', value:'table'})); 22 | newRule.push(postCss.decl({prop: 'width', value:'100%'})); 23 | break; 24 | case 'justify-content': 25 | console.log('justify-content'); 26 | atRule.push(postCss.decl({prop:'justify-content', value:decl.value})); 27 | newRule.push(postCss.decl(this._justifyContent(decl.value))); 28 | break; 29 | case 'align-items': 30 | console.log('align-items'); 31 | atRule.push(postCss.decl({prop: 'align-items', value: decl.value})); 32 | childRule.push(postCss.decl(this._alignItems(decl.value))); 33 | break; 34 | default: 35 | console.log('other:', decl.prop); 36 | newRule.push(decl); 37 | break; 38 | } 39 | 40 | }.bind(this)); 41 | 42 | // var wrappedRule = postCss.rule({nodes: newRule}); 43 | 44 | return { atRule: atRule, rule: newRule, childRule:childRule }; 45 | }, 46 | _justifyContent: function(value) { 47 | switch (value) { 48 | case 'flex-start': 49 | return {prop: 'text-align', value: 'left'}; 50 | break; 51 | case 'flex-end': 52 | return {prop: 'text-align', value: 'right'}; 53 | break; 54 | case 'center': 55 | return {prop: 'text-align', value: 'center'}; 56 | break; 57 | case 'space-between': 58 | // TODO make work with PostCSS helpers 59 | console.warn('space-between not yet supported, using center'); 60 | return {prop: 'text-align', value: 'center'}; 61 | break; 62 | case 'space-around': 63 | // TODO make work with PostCSS helpers 64 | console.warn('space-around not yet supported, using center'); 65 | return {prop: 'text-align', value: 'center'}; 66 | break; 67 | default: 68 | // TODO make work with PostCSS helpers 69 | console.warn('improper value given for justify-content, using center'); 70 | return {prop: 'text-align', value: 'center'}; 71 | break; 72 | } 73 | }, 74 | _alignItems: function(value) { 75 | switch (value) { 76 | case 'flex-start': 77 | return {prop: 'vertical-align', value: 'top'}; 78 | break; 79 | case 'flex-end': 80 | return {prop: 'vertical-align', value: 'bottom'}; 81 | break; 82 | case 'center': 83 | return {prop: 'vertical-align', value: 'middle'}; 84 | break; 85 | case 'stretch': 86 | // TODO make work with PostCSS helpers 87 | console.warn('stretch not yet supported, using center'); 88 | return {prop: 'vertical-align', value: 'middle'}; 89 | break; 90 | case 'baseline': 91 | // TODO make work with PostCSS helpers 92 | console.warn('baseline not yet supported, using CSS table\'s baseline'); 93 | return {prop: 'vertical-align', value: 'baseline'}; 94 | break; 95 | default: 96 | // TODO make work with PostCSS helpers 97 | console.warn('improper value given for justify-content, using baseline'); 98 | return {prop: 'vertical-align', value: 'baseline'}; 99 | break; 100 | } 101 | }, 102 | }; 103 | --------------------------------------------------------------------------------