├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── lib ├── fixes │ ├── flexbox_IE2012.js │ ├── prefixProperty.js │ ├── renameProperty.js │ └── renameValue.js ├── index.js └── merge.js ├── package.json ├── src ├── fixes │ ├── flexbox_IE2012.js │ ├── prefixProperty.js │ ├── renameProperty.js │ └── renameValue.js ├── index.js └── merge.js └── test ├── describe.js ├── fixes ├── flexbox_IE2012.js ├── prefixProperty.js ├── renameProperty.js └── renameValue.js ├── index.js └── merge.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | stage: 0, 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2015 Louis Acresti 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **THIS PACKAGE IS NO LONGER MAINTAINED** 2 | 3 | Use **[rofrischmann/inline-style-prefixer](https://github.com/rofrischmann/inline-style-prefixer)** instead! :heart: 4 | 5 | ---- 6 | 7 | # prefix-lite 8 | 9 | **NOTE:** This is experimental software; please [report issues](https://github.com/namuol/prefix-lite/issues). 10 | 11 | A **lightweight**, **isometric** solution for prefixing styles in JavaScript. 12 | 13 | ```js 14 | import prefix from 'prefix-lite'; 15 | 16 | const prefixed = prefix({ 17 | display: 'flex', 18 | flexDirection: 'column', 19 | justifyContent: 'flex-end', 20 | flexOrder: 3, 21 | 22 | filter: 'blur(500px)', 23 | }); 24 | 25 | console.log(prefixed); 26 | 27 | // Result: 28 | // { 29 | // display: [ 30 | // 'flex', 31 | // '-webkit-flex', 32 | // '-ms-flexbox' 33 | // ], 34 | // flexDirection: 'column', 35 | // justifyContent: 'flex-end', 36 | // flexOrder: 3, 37 | // filter: 'blur(500px)', 38 | // MozJustifyContent: 'flex-end', 39 | // MsJustifyContent: 'flex-end', 40 | // OJustifyContent: 'flex-end', 41 | // WebkitJustifyContent: 'flex-end', 42 | // MsFlexPack: 'end', 43 | // MozFilter: 'blur(500px)', 44 | // MsFilter: 'blur(500px)', 45 | // OFilter: 'blur(500px)', 46 | // WebkitFilter: 'blur(500px)' 47 | // } 48 | ``` 49 | 50 | ## Why not just use Autoprefixer? 51 | 52 | This project is for people who need to render dynamic styles **in the browser**, and was designed to be used with [free-style](https://github.com/blakeembrey/free-style). 53 | 54 | Autoprefix was never really meant to run client-side; bundling it will add **several megabytes** to your bundle size. 55 | 56 | ## Why not just use -prefix-free, et al? 57 | 58 | `-prefix-free` is an awesome solution, but wont solve your problem if you want to serve static CSS that 59 | is immediately-viewable; furthermore, if you serve your CSS over HTTPS, many browsers will throw security exceptions. 60 | 61 | ## License 62 | 63 | MIT 64 | 65 | ## Install 66 | 67 | ```sh 68 | npm install prefix-lite 69 | ``` 70 | -------------------------------------------------------------------------------- /lib/fixes/flexbox_IE2012.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | exports['default'] = flexbox_IE2012; 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12 | 13 | var _merge = require('../merge'); 14 | 15 | var _merge2 = _interopRequireDefault(_merge); 16 | 17 | var FLEX_PROPERTIES = { 18 | alignItems: ['MsFlexAlign'], 19 | alignContent: ['MsFlexLinePack'], 20 | justifyContent: ['MsFlexPack'], 21 | flexGrow: ['MsFlexPositive'], 22 | flexShrink: ['MsFlexNegative'] 23 | }; 24 | 25 | var renameProperty = require('./renameProperty').config({ 26 | alternateProperties: FLEX_PROPERTIES 27 | }); 28 | 29 | var renameValue = require('./renameValue').config({ 30 | alternateValues: { 31 | 'flex': ['-ms-flexbox'], 32 | 'flex-start': ['start'], 33 | 'flex-end': ['end'], 34 | 'space-around': ['distribute'], 35 | 'space-between': ['justify'] 36 | } 37 | }); 38 | 39 | function flexbox_IE2012(prop, value) { 40 | var base = {}; 41 | base[prop] = value; 42 | 43 | var propertyResults = _extends({}, base, renameProperty(prop, value)); 44 | 45 | var result = Object.keys(propertyResults).reduce(function (result, prop) { 46 | if (Object.keys(FLEX_PROPERTIES).indexOf(prop) > -1) { 47 | return result; 48 | } 49 | 50 | var base = {}; 51 | base[prop] = propertyResults[prop]; 52 | 53 | var withRenamedValues = renameValue(prop, propertyResults[prop]); 54 | 55 | return _extends({}, result, base, withRenamedValues); 56 | }, {}); 57 | 58 | return result; 59 | } 60 | 61 | module.exports = exports['default']; -------------------------------------------------------------------------------- /lib/fixes/prefixProperty.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports.config = config; 7 | var ALL = ['Moz', 'Ms', 'O', 'Webkit']; 8 | 9 | var WEBKIT = ['Webkit']; 10 | var WEBKIT_MOZ = ['Webkit', 'Moz']; 11 | var WEBKIT_MS = ['Webkit', 'Ms']; 12 | 13 | var DEFAULT_CONFIG = { 14 | propertyPrefixes: { 15 | 'alignContent': WEBKIT, 16 | 'alignItems': WEBKIT, 17 | 'animation': WEBKIT, 18 | 'animationDelay': WEBKIT, 19 | 'animationDirection': WEBKIT, 20 | 'animationDuration': WEBKIT, 21 | 'animationFillMode': WEBKIT, 22 | 'animationIterationCount': WEBKIT, 23 | 'animationName': WEBKIT, 24 | 'animationPlayState': WEBKIT, 25 | 'animationTimingFunction': WEBKIT, 26 | 'appearance': WEBKIT_MOZ, 27 | 'backfaceVisibility': WEBKIT_MOZ, 28 | 'contentColumns': ALL, 29 | 'filter': WEBKIT, 30 | 'flexDirection': WEBKIT_MS, 31 | 'flexGrow': WEBKIT, 32 | 'flexShrink': WEBKIT, 33 | 'flexWrap': WEBKIT_MS, 34 | 'justifyContent': WEBKIT, 35 | 'perspective': ALL, 36 | 'perspectiveOrigin': ALL, 37 | 'transform': ALL, 38 | 'transformOrigin': ALL, 39 | 'transformStyle': ALL, 40 | 'transition': ALL, 41 | 'transitionDelay': ALL, 42 | 'transitionDuration': ALL, 43 | 'transitionProperty': ALL, 44 | 'transitionTimingFunction': ALL, 45 | 'userSelect': ALL 46 | } 47 | }; 48 | 49 | function config(_ref) { 50 | var propertyPrefixes = _ref.propertyPrefixes; 51 | var prefixes = _ref.prefixes; 52 | 53 | var propertyNames = Object.keys(propertyPrefixes); 54 | 55 | function matches(prop, value) { 56 | return propertyNames.indexOf(prop) > -1; 57 | } 58 | 59 | return function prefixProperty(prop, value) { 60 | if (!matches(prop, value)) { 61 | return {}; 62 | } 63 | 64 | var prefixes = propertyPrefixes[prop]; 65 | 66 | return prefixes.reduce(function (result, prefix) { 67 | result[prefix + prop[0].toUpperCase() + prop.substr(1)] = value; 68 | return result; 69 | }, {}); 70 | }; 71 | } 72 | 73 | exports['default'] = config(DEFAULT_CONFIG); -------------------------------------------------------------------------------- /lib/fixes/renameProperty.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.config = config; 7 | var DEFAULT_CONFIG = { 8 | alternateProperties: {} 9 | }; 10 | 11 | function config(_ref) { 12 | var alternateProperties = _ref.alternateProperties; 13 | 14 | var propertyNames = Object.keys(alternateProperties); 15 | 16 | function matches(prop, value) { 17 | return propertyNames.indexOf(prop) > -1; 18 | } 19 | 20 | return function renameProperty(prop, value) { 21 | if (!matches(prop)) { 22 | return {}; 23 | } 24 | 25 | var alternates = alternateProperties[prop]; 26 | 27 | return alternates.reduce(function (result, alternate) { 28 | result[alternate] = value; 29 | return result; 30 | }, {}); 31 | }; 32 | } 33 | 34 | exports["default"] = config(DEFAULT_CONFIG); -------------------------------------------------------------------------------- /lib/fixes/renameValue.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | var _bind = Function.prototype.bind; 7 | exports.config = config; 8 | 9 | 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); } } 10 | 11 | var DEFAULT_CONFIG = { 12 | alternateValues: { 13 | 'flex': ['-webkit-box', '-webkit-flex'] 14 | } 15 | }; 16 | 17 | function config(_ref) { 18 | var alternateValues = _ref.alternateValues; 19 | 20 | var valueNames = Object.keys(alternateValues); 21 | 22 | function matches(value) { 23 | return valueNames.indexOf(value) > -1; 24 | } 25 | 26 | return function renameValue(prop, value) { 27 | if (!matches(value)) { 28 | return {}; 29 | } 30 | 31 | var alternates = alternateValues[value]; 32 | var result = {}; 33 | if (alternates.length > 1) { 34 | result[prop] = new (_bind.apply(Array, [null].concat(_toConsumableArray(alternates))))(); 35 | } else if (alternates.length === 1) { 36 | result[prop] = alternates[0]; 37 | } 38 | 39 | return result; 40 | }; 41 | } 42 | 43 | exports['default'] = config(DEFAULT_CONFIG); -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports.config = config; 7 | 8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 9 | 10 | var _fixesPrefixProperty = require('./fixes/prefixProperty'); 11 | 12 | var _fixesPrefixProperty2 = _interopRequireDefault(_fixesPrefixProperty); 13 | 14 | var _fixesRenameProperty = require('./fixes/renameProperty'); 15 | 16 | var _fixesRenameProperty2 = _interopRequireDefault(_fixesRenameProperty); 17 | 18 | var _fixesRenameValue = require('./fixes/renameValue'); 19 | 20 | var _fixesRenameValue2 = _interopRequireDefault(_fixesRenameValue); 21 | 22 | var _fixesFlexbox_IE2012 = require('./fixes/flexbox_IE2012'); 23 | 24 | var _fixesFlexbox_IE20122 = _interopRequireDefault(_fixesFlexbox_IE2012); 25 | 26 | var _merge = require('./merge'); 27 | 28 | var _merge2 = _interopRequireDefault(_merge); 29 | 30 | var DEFAULT_CONFIG = { 31 | mutators: [_fixesPrefixProperty2['default'], 32 | // renameProperty, 33 | _fixesRenameValue2['default'], _fixesFlexbox_IE20122['default']] 34 | }; 35 | 36 | function config(_ref) { 37 | var mutators = _ref.mutators; 38 | 39 | return function prefixLite(style) { 40 | return Object.keys(style).reduce(function (result, prop) { 41 | var styleProp = style[prop]; 42 | 43 | return mutators.reduce(function (result, mutate) { 44 | if (Array.isArray(styleProp)) { 45 | return styleProp.reduce(function (result, value) { 46 | return (0, _merge2['default'])(result, mutate(prop, value)); 47 | }, result); 48 | } else if (typeof styleProp === 'object') { 49 | result[prop] = prefixLite(styleProp); 50 | return result; 51 | } else { 52 | return (0, _merge2['default'])(result, mutate(prop, styleProp)); 53 | } 54 | }, result); 55 | }, style); 56 | }; 57 | } 58 | 59 | var DEFAULT = config(DEFAULT_CONFIG); 60 | 61 | exports['default'] = DEFAULT; -------------------------------------------------------------------------------- /lib/merge.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | exports["default"] = merge; 10 | 11 | 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); } } 12 | 13 | function merge(a, b) { 14 | return Object.keys(a).reduce(function (result, key) { 15 | var aval = a[key]; 16 | var bval = b[key]; 17 | 18 | if (!!bval && bval !== aval) { 19 | (function () { 20 | var values = new Set(); 21 | 22 | if (Array.isArray(aval)) { 23 | aval.forEach(function (val) { 24 | return values.add(val); 25 | }); 26 | } else { 27 | values.add(aval); 28 | } 29 | 30 | if (Array.isArray(bval)) { 31 | bval.forEach(function (val) { 32 | return values.add(val); 33 | }); 34 | } else { 35 | values.add(bval); 36 | } 37 | 38 | result[key] = [].concat(_toConsumableArray(values)); 39 | })(); 40 | } 41 | 42 | return result; 43 | }, _extends({}, a, b)); 44 | } 45 | 46 | module.exports = exports["default"]; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prefix-lite", 3 | "version": "0.0.2", 4 | "description": "prefix your CSS in JS without bloating your bundles", 5 | "main": "./lib/index.js", 6 | "scripts": { 7 | "test": "babel-node test | tap-difflet", 8 | "prepublish": "npm run build", 9 | "build": "babel src -d lib" 10 | }, 11 | "keywords": [ 12 | "prefix", 13 | "css", 14 | "autoprefix", 15 | "lightweight", 16 | "lite", 17 | "light", 18 | "weight", 19 | "browser" 20 | ], 21 | "author": "Louis Acresti (http://namuol.github.io)", 22 | "license": "MIT", 23 | "devDependencies": { 24 | "babel": "^5.8.20", 25 | "tap-difflet": "^0.3.0", 26 | "tape": "^4.0.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/fixes/flexbox_IE2012.js: -------------------------------------------------------------------------------- 1 | const FLEX_PROPERTIES = { 2 | alignItems: [ 3 | 'MsFlexAlign', 4 | ], 5 | alignContent: [ 6 | 'MsFlexLinePack', 7 | ], 8 | justifyContent: [ 9 | 'MsFlexPack', 10 | ], 11 | flexGrow: [ 12 | 'MsFlexPositive', 13 | ], 14 | flexShrink: [ 15 | 'MsFlexNegative', 16 | ], 17 | }; 18 | 19 | const renameProperty = require('./renameProperty').config({ 20 | alternateProperties: FLEX_PROPERTIES, 21 | }); 22 | 23 | const renameValue = require('./renameValue').config({ 24 | alternateValues: { 25 | 'flex': [ 26 | '-ms-flexbox', 27 | ], 28 | 'flex-start': [ 29 | 'start', 30 | ], 31 | 'flex-end': [ 32 | 'end', 33 | ], 34 | 'space-around': [ 35 | 'distribute', 36 | ], 37 | 'space-between': [ 38 | 'justify', 39 | ], 40 | }, 41 | }); 42 | 43 | import merge from '../merge'; 44 | 45 | export default function flexbox_IE2012 (prop, value) { 46 | const base = {}; 47 | base[prop] = value; 48 | 49 | const propertyResults = {...base, ...renameProperty(prop, value)}; 50 | 51 | const result = Object.keys(propertyResults).reduce((result, prop) => { 52 | if (Object.keys(FLEX_PROPERTIES).indexOf(prop) > -1) { 53 | return result; 54 | } 55 | 56 | const base = {}; 57 | base[prop] = propertyResults[prop]; 58 | 59 | const withRenamedValues = renameValue(prop, propertyResults[prop]); 60 | 61 | return {...result, ...base, ...withRenamedValues}; 62 | }, {}); 63 | 64 | return result; 65 | } 66 | -------------------------------------------------------------------------------- /src/fixes/prefixProperty.js: -------------------------------------------------------------------------------- 1 | const ALL = [ 2 | 'Moz', 3 | 'Ms', 4 | 'O', 5 | 'Webkit', 6 | ]; 7 | 8 | const WEBKIT = ['Webkit']; 9 | const WEBKIT_MOZ = ['Webkit', 'Moz']; 10 | const WEBKIT_MS = ['Webkit', 'Ms']; 11 | 12 | const DEFAULT_CONFIG = { 13 | propertyPrefixes: { 14 | 'alignContent': WEBKIT, 15 | 'alignItems': WEBKIT, 16 | 'animation': WEBKIT, 17 | 'animationDelay': WEBKIT, 18 | 'animationDirection': WEBKIT, 19 | 'animationDuration': WEBKIT, 20 | 'animationFillMode': WEBKIT, 21 | 'animationIterationCount': WEBKIT, 22 | 'animationName': WEBKIT, 23 | 'animationPlayState': WEBKIT, 24 | 'animationTimingFunction': WEBKIT, 25 | 'appearance': WEBKIT_MOZ, 26 | 'backfaceVisibility': WEBKIT_MOZ, 27 | 'contentColumns': ALL, 28 | 'filter': WEBKIT, 29 | 'flexDirection': WEBKIT_MS, 30 | 'flexGrow': WEBKIT, 31 | 'flexShrink': WEBKIT, 32 | 'flexWrap': WEBKIT_MS, 33 | 'justifyContent': WEBKIT, 34 | 'perspective': ALL, 35 | 'perspectiveOrigin': ALL, 36 | 'transform': ALL, 37 | 'transformOrigin': ALL, 38 | 'transformStyle': ALL, 39 | 'transition': ALL, 40 | 'transitionDelay': ALL, 41 | 'transitionDuration': ALL, 42 | 'transitionProperty': ALL, 43 | 'transitionTimingFunction': ALL, 44 | 'userSelect': ALL, 45 | }, 46 | } 47 | 48 | export function config ({propertyPrefixes, prefixes}) { 49 | const propertyNames = Object.keys(propertyPrefixes); 50 | 51 | function matches (prop, value) { 52 | return propertyNames.indexOf(prop) > -1; 53 | } 54 | 55 | return function prefixProperty (prop, value) { 56 | if (!matches(prop, value)) { 57 | return {}; 58 | } 59 | 60 | const prefixes = propertyPrefixes[prop]; 61 | 62 | return prefixes.reduce((result, prefix) => { 63 | result[prefix + prop[0].toUpperCase() + prop.substr(1)] = value; 64 | return result; 65 | }, {}); 66 | } 67 | } 68 | 69 | export default config(DEFAULT_CONFIG); -------------------------------------------------------------------------------- /src/fixes/renameProperty.js: -------------------------------------------------------------------------------- 1 | const DEFAULT_CONFIG = { 2 | alternateProperties: { 3 | }, 4 | }; 5 | 6 | export function config ({alternateProperties}) { 7 | const propertyNames = Object.keys(alternateProperties); 8 | 9 | function matches (prop, value) { 10 | return propertyNames.indexOf(prop) > -1; 11 | } 12 | 13 | return function renameProperty (prop, value) { 14 | if (!matches(prop)) { 15 | return {}; 16 | } 17 | 18 | const alternates = alternateProperties[prop]; 19 | 20 | return alternates.reduce((result, alternate) => { 21 | result[alternate] = value; 22 | return result; 23 | }, {}); 24 | } 25 | } 26 | 27 | export default config(DEFAULT_CONFIG); -------------------------------------------------------------------------------- /src/fixes/renameValue.js: -------------------------------------------------------------------------------- 1 | const DEFAULT_CONFIG = { 2 | alternateValues: { 3 | 'flex': [ 4 | '-webkit-box', 5 | '-webkit-flex', 6 | ], 7 | }, 8 | }; 9 | 10 | export function config ({alternateValues}) { 11 | const valueNames = Object.keys(alternateValues); 12 | 13 | function matches (value) { 14 | return valueNames.indexOf(value) > -1; 15 | } 16 | 17 | return function renameValue (prop, value) { 18 | if (!matches(value)) { 19 | return {}; 20 | } 21 | 22 | const alternates = alternateValues[value]; 23 | const result = {}; 24 | if (alternates.length > 1) { 25 | result[prop] = new Array(...alternates); 26 | } else if (alternates.length === 1) { 27 | result[prop] = alternates[0]; 28 | } 29 | 30 | return result; 31 | } 32 | } 33 | 34 | export default config(DEFAULT_CONFIG); -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import prefixProperty from './fixes/prefixProperty'; 2 | import renameProperty from './fixes/renameProperty'; 3 | import renameValue from './fixes/renameValue'; 4 | import flexbox_IE2012 from './fixes/flexbox_IE2012'; 5 | 6 | import merge from './merge'; 7 | 8 | const DEFAULT_CONFIG = { 9 | mutators: [ 10 | prefixProperty, 11 | // renameProperty, 12 | renameValue, 13 | flexbox_IE2012, 14 | ], 15 | }; 16 | 17 | export function config ({mutators}) { 18 | return function prefixLite (style) { 19 | return Object.keys(style).reduce((result, prop) => { 20 | const styleProp = style[prop]; 21 | 22 | return mutators.reduce((result, mutate) => { 23 | if (Array.isArray(styleProp)) { 24 | return styleProp.reduce((result, value) => { 25 | return merge(result, mutate(prop, value)); 26 | }, result); 27 | } else if (typeof styleProp === 'object') { 28 | result[prop] = prefixLite(styleProp); 29 | return result; 30 | } else { 31 | return merge(result, mutate(prop, styleProp)); 32 | } 33 | }, result); 34 | 35 | }, style); 36 | }; 37 | } 38 | 39 | const DEFAULT = config(DEFAULT_CONFIG); 40 | 41 | export default DEFAULT; -------------------------------------------------------------------------------- /src/merge.js: -------------------------------------------------------------------------------- 1 | export default function merge (a, b) { 2 | return Object.keys(a).reduce((result, key) => { 3 | const aval = a[key]; 4 | const bval = b[key]; 5 | 6 | if (!!bval && bval !== aval) { 7 | const values = new Set; 8 | 9 | if (Array.isArray(aval)) { 10 | aval.forEach(val => values.add(val)); 11 | } else { 12 | values.add(aval); 13 | } 14 | 15 | if (Array.isArray(bval)) { 16 | bval.forEach(val => values.add(val)); 17 | } else { 18 | values.add(bval); 19 | } 20 | 21 | result[key] = [...values]; 22 | } 23 | 24 | return result; 25 | }, {...a, ...b}); 26 | } 27 | -------------------------------------------------------------------------------- /test/describe.js: -------------------------------------------------------------------------------- 1 | import tape from 'tape'; 2 | 3 | export default function describe (item, cb) { 4 | function it (capability, test) { 5 | tape.test(`${item} ${capability}`, (t) => { 6 | test(t); 7 | }); 8 | } 9 | 10 | cb(it); 11 | } -------------------------------------------------------------------------------- /test/fixes/flexbox_IE2012.js: -------------------------------------------------------------------------------- 1 | import tape from 'tape'; 2 | import describe from '../describe'; 3 | 4 | import flexbox_IE2012 from '../../src/fixes/flexbox_IE2012'; 5 | 6 | describe('flexbox_IE2012', (it) => { 7 | it('should rename flex value to -ms-flexbox', (t) => { 8 | const actual = flexbox_IE2012('display', 'flex'); 9 | const expected = { 10 | display: '-ms-flexbox', 11 | }; 12 | 13 | t.deepEqual(actual, expected); 14 | 15 | t.end(); 16 | }); 17 | 18 | it('should rename flex-start to start and justifyContent to MsFlexPack', (t) => { 19 | const actual = flexbox_IE2012('justifyContent', 'flex-start'); 20 | const expected = { 21 | MsFlexPack: 'start', 22 | }; 23 | 24 | t.deepEqual(actual, expected); 25 | 26 | t.end(); 27 | }); 28 | 29 | it('should properly handle alignItems: center', (t) => { 30 | const actual = flexbox_IE2012('alignItems', 'center'); 31 | const expected = { 32 | MsFlexAlign: 'center', 33 | }; 34 | 35 | t.deepEqual(actual, expected); 36 | 37 | t.end(); 38 | }); 39 | 40 | 41 | }); -------------------------------------------------------------------------------- /test/fixes/prefixProperty.js: -------------------------------------------------------------------------------- 1 | import tape from 'tape'; 2 | import describe from '../describe'; 3 | 4 | import {config} from '../../src/fixes/prefixProperty'; 5 | 6 | describe('prefixProperty', (it) => { 7 | it('should add all specified prefixes', (t) => { 8 | const prefixProperty = config({ 9 | propertyPrefixes: { 10 | 'testProperty': ['Aa', 'Bb', 'Cc'], 11 | }, 12 | }); 13 | 14 | const actual = prefixProperty('testProperty', 'test-value'); 15 | const expected = { 16 | AaTestProperty: 'test-value', 17 | BbTestProperty: 'test-value', 18 | CcTestProperty: 'test-value', 19 | }; 20 | 21 | t.deepEqual(actual, expected); 22 | 23 | t.end(); 24 | }); 25 | 26 | it('should not prefix non-matching properties', (t) => { 27 | const prefixProperty = config({ 28 | propertyPrefixes: { 29 | 'testProperty': ['Aa', 'Bb', 'Cc'], 30 | }, 31 | }); 32 | 33 | const actual = prefixProperty('nonMatchingProperty', 'test-value'); 34 | const expected = { 35 | }; 36 | 37 | t.deepEqual(actual, expected); 38 | 39 | t.end(); 40 | }); 41 | }); -------------------------------------------------------------------------------- /test/fixes/renameProperty.js: -------------------------------------------------------------------------------- 1 | import tape from 'tape'; 2 | import describe from '../describe'; 3 | 4 | import {config} from '../../src/fixes/renameProperty'; 5 | 6 | describe('renameProperty', (it) => { 7 | it('should add all specified alternate properties', (t) => { 8 | const renameProperty = config({ 9 | alternateProperties: { 10 | testProperty: ['testProperty_a', 'testProperty_b'], 11 | }, 12 | }); 13 | 14 | const actual = renameProperty('testProperty', 'test-value'); 15 | const expected = { 16 | testProperty_a: 'test-value', 17 | testProperty_b: 'test-value', 18 | }; 19 | 20 | t.deepEqual(actual, expected); 21 | 22 | t.end(); 23 | }); 24 | }); -------------------------------------------------------------------------------- /test/fixes/renameValue.js: -------------------------------------------------------------------------------- 1 | import tape from 'tape'; 2 | import describe from '../describe'; 3 | 4 | import {config} from '../../src/fixes/renameValue'; 5 | 6 | describe('renameValue', (it) => { 7 | it('should add all specified alternate properties', (t) => { 8 | const renameValue = config({ 9 | alternateValues: { 10 | 'test-value': ['test-value-a', 'test-value-b'], 11 | }, 12 | }); 13 | 14 | const actual = renameValue('testProperty', 'test-value'); 15 | const expected = { 16 | testProperty: [ 17 | 'test-value-a', 18 | 'test-value-b', 19 | ], 20 | }; 21 | 22 | t.deepEqual(actual, expected); 23 | 24 | t.end(); 25 | }); 26 | 27 | it('should output non-array values when there\'s only one result', (t) => { 28 | const renameValue = config({ 29 | alternateValues: { 30 | 'test-value': ['test-value-a'], 31 | }, 32 | }); 33 | 34 | const actual = renameValue('testProperty', 'test-value'); 35 | const expected = { 36 | testProperty: 'test-value-a', 37 | }; 38 | 39 | t.deepEqual(actual, expected); 40 | 41 | t.end(); 42 | }); 43 | }); -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | import './merge'; 5 | 6 | const tests = fs.readdirSync(path.join(__dirname, 'fixes')).forEach((testFile) => { 7 | require(path.join(__dirname, 'fixes', testFile)); 8 | }); 9 | -------------------------------------------------------------------------------- /test/merge.js: -------------------------------------------------------------------------------- 1 | import tape from 'tape'; 2 | import describe from './describe'; 3 | 4 | import merge from '../src/merge'; 5 | 6 | describe('merge', (it) => { 7 | it('should cleanly merge empty objects', (t) => { 8 | const actual = merge({}, {}); 9 | const expected = {}; 10 | 11 | t.deepEqual(actual, expected); 12 | 13 | t.end(); 14 | }); 15 | 16 | it('should combine unique key:value pairs from both objects', (t) => { 17 | const actual = merge({a:1}, {b:2}); 18 | const expected = {a:1, b:2}; 19 | 20 | t.deepEqual(actual, expected); 21 | 22 | t.end(); 23 | }); 24 | 25 | it('should create arrays containing both values for duplicate properties', (t) => { 26 | const actual = merge({a:1}, {a:2}); 27 | const expected = {a: [1, 2]}; 28 | 29 | t.deepEqual(actual, expected); 30 | 31 | t.end(); 32 | }); 33 | 34 | it('should merge arrays of values', (t) => { 35 | const actual = merge({a:[1,2]}, {a:[3,4]}); 36 | const expected = {a: [1, 2, 3, 4]}; 37 | 38 | t.deepEqual(actual, expected); 39 | 40 | t.end(); 41 | }); 42 | 43 | it('should discard duplicates from arrays', (t) => { 44 | const actual = merge({a:1}, {a:[1,2,3,4]}); 45 | const expected = {a: [1, 2, 3, 4]}; 46 | 47 | t.deepEqual(actual, expected); 48 | 49 | t.end(); 50 | }); 51 | }); --------------------------------------------------------------------------------