Socket
Socket
Sign inDemoInstall

aphrodite

Package Overview
Dependencies
Maintainers
2
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

aphrodite - npm Package Compare versions

Comparing version 0.3.1 to 0.3.2

tests/util_test.js

214

dist/aphrodite.js

@@ -182,2 +182,11 @@ module.exports =

exports.mapObj = mapObj;
// Flattens an array one level
// [[A], [B, C, [D]]] -> [A, B, C, [D]]
var flatten = function flatten(list) {
return list.reduce(function (memo, x) {
return memo.concat(x);
}, []);
};
exports.flatten = flatten;
var UPPERCASE_RE = /([A-Z])/g;

@@ -360,12 +369,10 @@ var MS_RE = /^ms-/;

exports.hashObject = hashObject;
var IMPORTANT_RE = /^([^:]+:.*?)( !important)?$/;
var IMPORTANT_RE = /^([^:]+:.*?)( !important)?;$/;
// Given a style string like "a: b; c: d;", adds !important to each of the
// properties to generate "a: b !important; c: d !important;".
// Given a single style rule string like "a: b;", adds !important to generate
// "a: b !important;".
var importantify = function importantify(string) {
return string.split(";").map(function (str) {
return str.replace(IMPORTANT_RE, function (_, base, important) {
return base + " !important";
});
}).join(";");
return string.replace(IMPORTANT_RE, function (_, base, important) {
return base + " !important;";
});
};

@@ -944,3 +951,3 @@ exports.importantify = importantify;

var rules = (0, _util.objectToPairs)(prefixedDeclarations).map(function (_ref) {
var prefixedRules = (0, _util.flatten)((0, _util.objectToPairs)(prefixedDeclarations).map(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2);

@@ -951,2 +958,39 @@

if (Array.isArray(value)) {
var _ret = (function () {
// inline-style-prefix-all returns an array when there should be
// multiple rules, we will flatten to single rules
var prefixedValues = [];
var unprefixedValues = [];
value.forEach(function (v) {
if (v.indexOf('-') === 0) {
prefixedValues.push(v);
} else {
unprefixedValues.push(v);
}
});
prefixedValues.sort();
unprefixedValues.sort();
return {
v: prefixedValues.concat(unprefixedValues).map(function (v) {
return [key, v];
})
};
})();
if (typeof _ret === 'object') return _ret.v;
}
return [[key, value]];
}));
var rules = prefixedRules.map(function (_ref3) {
var _ref32 = _slicedToArray(_ref3, 2);
var key = _ref32[0];
var value = _ref32[1];
var stringValue = (0, _util.stringifyValue)(key, value);

@@ -994,19 +1038,19 @@ var ret = (0, _util.kebabifyStyleName)(key) + ':' + stringValue + ';';

var _pluginsCursor = __webpack_require__(14);
var _pluginsCursor = __webpack_require__(15);
var _pluginsCursor2 = _interopRequireDefault(_pluginsCursor);
var _pluginsFlex = __webpack_require__(15);
var _pluginsFlex = __webpack_require__(16);
var _pluginsFlex2 = _interopRequireDefault(_pluginsFlex);
var _pluginsSizing = __webpack_require__(16);
var _pluginsSizing = __webpack_require__(17);
var _pluginsSizing2 = _interopRequireDefault(_pluginsSizing);
var _pluginsGradient = __webpack_require__(17);
var _pluginsGradient = __webpack_require__(18);
var _pluginsGradient2 = _interopRequireDefault(_pluginsGradient);
var _pluginsTransition = __webpack_require__(18);
var _pluginsTransition = __webpack_require__(19);

@@ -1036,3 +1080,3 @@ var _pluginsTransition2 = _interopRequireDefault(_pluginsTransition);

var value = styles[property];
if (value instanceof Object) {
if (value instanceof Object && !Array.isArray(value)) {
// recurse through nested style objects

@@ -1128,4 +1172,10 @@ prefixedStyles[property] = prefixAll(value);

var _utilsIsPrefixedValue = __webpack_require__(14);
var _utilsIsPrefixedValue2 = _interopRequireDefault(_utilsIsPrefixedValue);
function calc(property, value) {
if (typeof value === 'string' && value.indexOf('calc(') > -1) {
if ((0, _utilsIsPrefixedValue2['default'])(value)) return;
return (0, _utilsJoinPrefixedRules2['default'])(property, value, function (prefix, value) {

@@ -1166,3 +1216,3 @@ return value.replace(/calc\(/g, prefix + 'calc(');

return replacer(prefix, value);
}).join(';' + (0, _camelToDashCase2['default'])(property) + ':'));
}));
})();

@@ -1197,2 +1247,20 @@ };

/* 14 */
/***/ function(module, exports) {
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports['default'] = function (value) {
if (Array.isArray(value)) value = value.join(',');
return value.match(/-webkit-|-moz-|-ms-/) !== null;
};
module.exports = exports['default'];
/***/ },
/* 15 */
/***/ function(module, exports, __webpack_require__) {

@@ -1229,3 +1297,3 @@

/***/ },
/* 15 */
/* 16 */
/***/ function(module, exports, __webpack_require__) {

@@ -1246,6 +1314,3 @@

var values = {
'flex': true,
'inline-flex': true
};
var values = { flex: true, 'inline-flex': true };

@@ -1255,3 +1320,3 @@ function flex(property, value) {

return {
display: ['-webkit-box', '-moz-box', '-ms-' + value + 'box', '-webkit-' + value, value].join(';' + (0, _utilsCamelToDashCase2['default'])(property) + ':')
display: ['-webkit-box', '-moz-box', '-ms-' + value + 'box', '-webkit-' + value, value]
};

@@ -1264,3 +1329,3 @@ }

/***/ },
/* 16 */
/* 17 */
/***/ function(module, exports, __webpack_require__) {

@@ -1307,3 +1372,3 @@

/***/ },
/* 17 */
/* 18 */
/***/ function(module, exports, __webpack_require__) {

@@ -1324,2 +1389,6 @@

var _utilsIsPrefixedValue = __webpack_require__(14);
var _utilsIsPrefixedValue2 = _interopRequireDefault(_utilsIsPrefixedValue);
var values = /linear-gradient|radial-gradient|repeating-linear-gradient|repeating-radial-gradient/;

@@ -1329,2 +1398,4 @@

if (typeof value === 'string' && value.match(values) !== null) {
if ((0, _utilsIsPrefixedValue2['default'])(value)) return;
return (0, _utilsJoinPrefixedRules2['default'])(property, value);

@@ -1337,3 +1408,3 @@ }

/***/ },
/* 18 */
/* 19 */
/***/ function(module, exports, __webpack_require__) {

@@ -1360,5 +1431,5 @@

var _utilsUnprefixProperty = __webpack_require__(19);
var _utilsIsPrefixedValue = __webpack_require__(14);
var _utilsUnprefixProperty2 = _interopRequireDefault(_utilsUnprefixProperty);
var _utilsIsPrefixedValue2 = _interopRequireDefault(_utilsIsPrefixedValue);

@@ -1369,67 +1440,56 @@ var _prefixProps = __webpack_require__(8);

var properties = { transition: true, transitionProperty: true };
var properties = {
transition: true,
transitionProperty: true,
WebkitTransition: true,
WebkitTransitionProperty: true
};
function transition(property, value) {
// also check for already prefixed transitions
var unprefixedProperty = (0, _utilsUnprefixProperty2['default'])(property);
if (typeof value === 'string' && properties[unprefixedProperty]) {
if (typeof value === 'string' && properties[property]) {
var _ref2;
var _ret = (function () {
// only split multi values, not cubic beziers
var multipleValues = value.split(/,(?![^()]*(?:\([^()]*\))?\))/g);
var outputValue = prefixValue(value);
var webkitOutput = outputValue.split(',').filter(function (value) {
return value.match(/-moz-|-ms-/) === null;
}).join(',');
// iterate each single value and check for transitioned properties
// that need to be prefixed as well
multipleValues.forEach(function (val, index) {
multipleValues[index] = Object.keys(_prefixProps2['default']).reduce(function (out, prefix) {
var dashCasePrefix = '-' + prefix.toLowerCase() + '-';
// if the property is already prefixed
if (property.indexOf('Webkit') > -1) {
return _defineProperty({}, property, webkitOutput);
}
Object.keys(_prefixProps2['default'][prefix]).forEach(function (prop) {
var dashCaseProperty = (0, _utilsCamelToDashCase2['default'])(prop);
if (val.indexOf(dashCaseProperty) > -1) {
// join all prefixes and create a new value
out = val.replace(dashCaseProperty, dashCasePrefix + dashCaseProperty) + ',' + out;
}
});
return out;
}, val);
});
var outputValue = multipleValues.join(',');
if (unprefixedProperty !== property) {
return {
v: _defineProperty({}, property, outputValue)
};
}
return {
v: (_ref2 = {}, _defineProperty(_ref2, 'Webkit' + (0, _utilsCapitalizeString2['default'])(property), outputValue.split(',').filter(function (value) {
return value.match(/-moz-|-ms-/) === null;
}).join(',')), _defineProperty(_ref2, property, outputValue), _ref2)
};
})();
if (typeof _ret === 'object') return _ret.v;
return _ref2 = {}, _defineProperty(_ref2, 'Webkit' + (0, _utilsCapitalizeString2['default'])(property), webkitOutput), _defineProperty(_ref2, property, outputValue), _ref2;
}
}
module.exports = exports['default'];
function prefixValue(value) {
if ((0, _utilsIsPrefixedValue2['default'])(value)) {
return value;
}
/***/ },
/* 19 */
/***/ function(module, exports) {
// only split multi values, not cubic beziers
var multipleValues = value.split(/,(?![^()]*(?:\([^()]*\))?\))/g);
'use strict';
// iterate each single value and check for transitioned properties
// that need to be prefixed as well
multipleValues.forEach(function (val, index) {
multipleValues[index] = Object.keys(_prefixProps2['default']).reduce(function (out, prefix) {
var dashCasePrefix = '-' + prefix.toLowerCase() + '-';
Object.defineProperty(exports, '__esModule', {
value: true
});
Object.keys(_prefixProps2['default'][prefix]).forEach(function (prop) {
var dashCaseProperty = (0, _utilsCamelToDashCase2['default'])(prop);
exports['default'] = function (property) {
var unprefixed = property.replace(/^(ms|Webkit|Moz|O)/, '');
return unprefixed.charAt(0).toLowerCase() + unprefixed.slice(1);
};
if (val.indexOf(dashCaseProperty) > -1) {
// join all prefixes and create a new value
out = val.replace(dashCaseProperty, dashCasePrefix + dashCaseProperty) + ',' + out;
}
});
return out;
}, val);
});
return multipleValues.join(',');
}
module.exports = exports['default'];

@@ -1436,0 +1496,0 @@

{
"name": "aphrodite",
"version": "0.3.1",
"version": "0.3.2",
"description": "Inline styles in JS that just work (TM)",

@@ -12,4 +12,6 @@ "keywords": [

"scripts": {
"test": "mocha --compilers js:babel/register tests",
"test:watch": "mocha --watch --compilers js:babel/register tests",
"test": "npm run coverage",
"coverage": "nyc --check-coverage --lines 100 --branches 100 npm run tests",
"tests": "mocha --compilers js:babel/register tests",
"tests:watch": "mocha --watch --compilers js:babel/register tests",
"prebuild": "rimraf dist lib",

@@ -46,2 +48,3 @@ "build": "npm-run-all --parallel build:*",

"npm-run-all": "^1.7.0",
"nyc": "^6.4.4",
"rimraf": "^2.5.2",

@@ -52,4 +55,4 @@ "webpack": "^1.12.2"

"asap": "^2.0.3",
"inline-style-prefix-all": "1.0.5"
"inline-style-prefix-all": "^2.0.0"
}
}

@@ -114,2 +114,29 @@ # Aphrodite: Inline Styles that work

Aphrodite uses [asap](https://github.com/kriskowal/asap) to schedule buffer flushing. If you measure DOM elements' dimensions in `componentDidMount` or `componentDidUpdate`, you can use `setTimeout` function to ensure all styles are injected.
```js
import { StyleSheetServer, css } from 'aphrodite';
class Component extends React.Component {
render() {
return <div ref="root" className={css(styles.div)} />;
}
componentDidMount() {
// At this point styles might not be injected yet.
this.refs.root.offsetHeight; // 0 or 10
setTimeout(() => {
this.refs.root.offsetHeight; // 10
}, 0);
}
}
const styles = StyleSheet.create({
div: {
height: 10,
},
});
```
# Server-side rendering

@@ -208,3 +235,3 @@

.small_ffd5jf:after {
.small_ffd5jf:before {
content: 'Aphrodite' !important;

@@ -214,2 +241,6 @@ }

# Tools
- [Aphrodite output tool](https://output.jsbin.com/qoseye) - Paste what you pass to `StyleSheet.create` and see the generated CSS
# TODO

@@ -216,0 +247,0 @@

@@ -5,3 +5,3 @@ import prefixAll from 'inline-style-prefix-all';

objectToPairs, kebabifyStyleName, recursiveMerge, stringifyValue,
importantify
importantify, flatten
} from './util';

@@ -66,3 +66,31 @@

const rules = objectToPairs(prefixedDeclarations).map(([key, value]) => {
const prefixedRules = flatten(
objectToPairs(prefixedDeclarations).map(([key, value]) => {
if (Array.isArray(value)) {
// inline-style-prefix-all returns an array when there should be
// multiple rules, we will flatten to single rules
const prefixedValues = [];
const unprefixedValues = [];
value.forEach(v => {
if (v.indexOf('-') === 0) {
prefixedValues.push(v);
} else {
unprefixedValues.push(v);
}
});
prefixedValues.sort();
unprefixedValues.sort();
return prefixedValues
.concat(unprefixedValues)
.map(v => [key, v]);
}
return [[key, value]];
})
);
const rules = prefixedRules.map(([key, value]) => {
const stringValue = stringifyValue(key, value);

@@ -69,0 +97,0 @@ const ret = `${kebabifyStyleName(key)}:${stringValue};`;

@@ -15,2 +15,6 @@ // {K1: V1, K2: V2, ...} -> [[K1, V1], [K2, V2]]

// Flattens an array one level
// [[A], [B, C, [D]]] -> [A, B, C, [D]]
export const flatten = (list) => list.reduce((memo, x) => memo.concat(x), []);
const UPPERCASE_RE = /([A-Z])/g;

@@ -184,12 +188,9 @@ const MS_RE = /^ms-/;

const IMPORTANT_RE = /^([^:]+:.*?)( !important)?$/;
const IMPORTANT_RE = /^([^:]+:.*?)( !important)?;$/;
// Given a style string like "a: b; c: d;", adds !important to each of the
// properties to generate "a: b !important; c: d !important;".
export const importantify = (string) => {
return string.split(";").map(
str => str.replace(
IMPORTANT_RE,
(_, base, important) => base + " !important")
).join(";");
};
// Given a single style rule string like "a: b;", adds !important to generate
// "a: b !important;".
export const importantify = (string) =>
string.replace(
IMPORTANT_RE,
(_, base, important) => base + " !important;");

@@ -56,2 +56,26 @@ import {assert} from 'chai';

});
it("doesn't break content strings which contain semicolons during importantify", () => {
assertCSSRuleset('.foo', {
content: '"foo;bar"'
}, '.foo{content:"foo;bar" !important;}');
});
it("doesn't break quoted url() arguments during importantify", () => {
assertCSSRuleset('.foo', {
background: 'url("data:image/svg+xml;base64,myImage")'
}, '.foo{background:url("data:image/svg+xml;base64,myImage") !important;}');
});
it("doesn't break unquoted url() arguments during importantify", () => {
assertCSSRuleset('.foo', {
background: 'url(data:image/svg+xml;base64,myImage)'
}, '.foo{background:url(data:image/svg+xml;base64,myImage) !important;}');
});
it("doesn't importantify rules that are already !important", () => {
assertCSSRuleset('.foo', {
color: 'blue !important',
}, '.foo{color:blue !important;}');
});
});

@@ -130,4 +154,4 @@ describe('generateCSS', () => {

display: 'flex',
}], '.foo{display:-webkit-box !important;display:-moz-box !important;display:-ms-flexbox !important;display:-webkit-flex !important;display:flex !important;}');
}], '.foo{display:-moz-box !important;display:-ms-flexbox !important;display:-webkit-box !important;display:-webkit-flex !important;display:flex !important;}');
});
});

@@ -257,2 +257,6 @@ import asap from 'asap';

});
it('doesn\'t fail with no argument passed in', () => {
StyleSheet.rehydrate();
});
});

@@ -259,0 +263,0 @@

@@ -75,2 +75,20 @@ import asap from 'asap';

it('doesn\'t inject the same style twice', done => {
injectStyleOnce("x", ".x", [{ color: "red" }], false);
injectStyleOnce("x", ".x", [{ color: "blue" }], false);
asap(() => {
const styleTags = global.document.getElementsByTagName("style");
assert.equal(styleTags.length, 1);
const styles = styleTags[0].textContent;
assert.include(styles, ".x{");
assert.include(styles, "color:red");
assert.notInclude(styles, "color:blue");
assert.equal(styles.match(/\.x{/g).length, 1);
done();
});
});
it('throws an error if we\'re not buffering and on the server', () => {

@@ -81,7 +99,42 @@ const oldDocument = global.document;

assert.throws(() => {
insertStyleOnce("x", ".x", [{ color: "red" }], false);
});
injectStyleOnce("x", ".x", [{ color: "red" }], false);
}, "Cannot automatically buffer");
global.document = oldDocument;
});
// browser-specific tests
it('adds to the .styleSheet.cssText if available', done => {
const styleTag = global.document.createElement("style");
styleTag.setAttribute("data-aphrodite", "");
document.head.appendChild(styleTag);
styleTag.styleSheet = { cssText: "" };
injectStyleOnce("x", ".x", [{ color: "red" }], false);
asap(() => {
assert.include(styleTag.styleSheet.cssText, ".x{");
assert.include(styleTag.styleSheet.cssText, "color:red");
done();
});
});
it('uses document.getElementsByTagName without document.head', done => {
Object.defineProperty(global.document, "head", {
value: null,
});
injectStyleOnce("x", ".x", [{ color: "red" }], false);
asap(() => {
const styleTags = global.document.getElementsByTagName("style");
assert.equal(styleTags.length, 1);
const styles = styleTags[0].textContent;
assert.include(styles, ".x{");
assert.include(styles, "color:red");
done();
});
});
});

@@ -101,2 +154,10 @@

});
it('throws an error if we try to buffer twice', () => {
startBuffering();
assert.throws(() => {
startBuffering();
}, "already buffering");
});
});

@@ -220,2 +281,60 @@

function assertStylesInclude(str) {
const styleTags = global.document.getElementsByTagName("style");
const styles = styleTags[0].textContent;
assert.include(styles, str);
}
describe('fontFamily', () => {
it('leaves plain strings alone', () => {
const sheet = StyleSheet.create({
base: {
fontFamily: "Helvetica",
},
});
startBuffering();
css(sheet.base);
flushToStyleTag();
assertStylesInclude('font-family:Helvetica !important');
});
it('concatenates arrays', () => {
const sheet = StyleSheet.create({
base: {
fontFamily: ["Helvetica", "sans-serif"],
},
});
startBuffering();
css(sheet.base);
flushToStyleTag();
assertStylesInclude('font-family:Helvetica,sans-serif !important');
});
it('adds @font-face rules for objects', () => {
const fontface = {
fontFamily: "CoolFont",
src: "url('coolfont.ttf')",
};
const sheet = StyleSheet.create({
base: {
fontFamily: [fontface, "sans-serif"],
},
});
startBuffering();
css(sheet.base);
flushToStyleTag();
assertStylesInclude('font-family:"CoolFont",sans-serif !important');
assertStylesInclude('font-family:CoolFont;');
assertStylesInclude("src:url('coolfont.ttf');");
});
});
describe('animationName', () => {

@@ -233,6 +352,3 @@ it('leaves plain strings alone', () => {

const styleTags = global.document.getElementsByTagName("style");
const styles = styleTags[0].textContent;
assert.include(styles, 'animation-name:boo !important');
assertStylesInclude('animation-name:boo !important');
});

@@ -261,2 +377,36 @@

assertStylesInclude('@keyframes keyframe_1ptfkz1');
assertStylesInclude('from{left:10px;}');
assertStylesInclude('50%{left:20px;}');
assertStylesInclude('to{left:40px;}');
assertStylesInclude('animation-name:keyframe_1ptfkz1');
});
it('doesn\'t add the same keyframes twice', () => {
const keyframes = {
'from': {
left: 10,
},
'50%': {
left: 20,
},
'to': {
left: 40,
},
};
const sheet = StyleSheet.create({
animate: {
animationName: keyframes,
},
animate2: {
animationName: keyframes,
},
});
startBuffering();
css(sheet.animate);
css(sheet.animate2);
flushToStyleTag();
const styleTags = global.document.getElementsByTagName("style");

@@ -266,8 +416,5 @@ const styles = styleTags[0].textContent;

assert.include(styles, '@keyframes keyframe_1ptfkz1');
assert.include(styles, 'from{left:10px;}');
assert.include(styles, '50%{left:20px;}');
assert.include(styles, 'to{left:40px;}');
assert.include(styles, 'animation-name:keyframe_1ptfkz1');
assert.equal(styles.match(/@keyframes/g).length, 1);
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc