babel-plugin-css-in-js
Advanced tools
Comparing version 1.4.1 to 1.5.0
@@ -12,2 +12,17 @@ # Changelog | ||
## v1.5.0 (January 22, 2016) | ||
- **New Feature** | ||
- Support basic theming via nesting in global selectors | ||
- **Internal** | ||
- Remove Node.js v4 and v5 from Travis | ||
- Add Node.js v7 to Travis | ||
## v1.4.1 (December 8, 2016) | ||
- **Bug Fix** | ||
- Don't return subselector expressions as style names (#23) | ||
- **Documentation** | ||
- Add section about global styles to README | ||
## v1.4.0 (August 24, 2016) | ||
@@ -14,0 +29,0 @@ |
@@ -31,3 +31,3 @@ 'use strict'; | ||
(0, _foreach2.default)(spec, function (value, key) { | ||
processStyle(css, key, value, 0, options); | ||
processStyle(css, key, value, 0, null, options); | ||
}); | ||
@@ -38,9 +38,10 @@ | ||
function processStyle(css, name, spec, level, options) { | ||
processRules(css, name, spec.rules, level, options); | ||
processSelectors(css, name, spec.selectors, level, options); | ||
processMediaQueries(css, name, spec.mediaQueries, level, options); | ||
function processStyle(css, name, spec, level, parent, options) { | ||
processRules(css, name, spec.rules, level, parent, options); | ||
processSelectors(css, name, spec.selectors, level, parent, options); | ||
processMediaQueries(css, name, spec.mediaQueries, level, parent, options); | ||
processParents(css, name, spec.parents, level, options); | ||
} | ||
function processRules(css, name, rules, level, options) { | ||
function processRules(css, name, rules, level, parent, options) { | ||
if (isEmpty(rules)) { | ||
@@ -50,3 +51,11 @@ return; | ||
var selector = name.charAt(0) === '$' ? name.substring(1) : '.' + (0, _generateClassName2.default)(name, options); | ||
var selector = void 0; | ||
if (name.charAt(0) === '$') { | ||
selector = name.substring(1); | ||
} else { | ||
selector = parent ? parent + ' ' : ''; | ||
selector += '.' + (0, _generateClassName2.default)(name, options); | ||
} | ||
css.push(indent(level) + selector + ' {'); | ||
@@ -61,3 +70,3 @@ | ||
function processSelectors(css, name, selectors, level, options) { | ||
function processSelectors(css, name, selectors, level, parent, options) { | ||
if (isEmpty(selectors)) { | ||
@@ -68,7 +77,7 @@ return; | ||
(0, _foreach2.default)(selectors, function (value, key) { | ||
processRules(css, name + key, value.rules, level, options); | ||
processRules(css, name + key, value.rules, level, parent, options); | ||
}); | ||
} | ||
function processMediaQueries(css, name, mediaQueries, level, options) { | ||
function processMediaQueries(css, name, mediaQueries, level, parent, options) { | ||
if (isEmpty(mediaQueries)) { | ||
@@ -79,11 +88,21 @@ return; | ||
(0, _foreach2.default)(mediaQueries, function (value, key) { | ||
processMediaQuery(css, name, key, value, level, options); | ||
processMediaQuery(css, name, key, value, level, parent, options); | ||
}); | ||
} | ||
function processMediaQuery(css, name, query, content, level, options) { | ||
function processParents(css, name, parents, level, options) { | ||
if (isEmpty(parents)) { | ||
return; | ||
} | ||
(0, _foreach2.default)(parents, function (spec, key) { | ||
processStyle(css, name, spec, level, key, options); | ||
}); | ||
} | ||
function processMediaQuery(css, name, query, content, level, parent, options) { | ||
var mediaQueryCSS = []; | ||
processRules(mediaQueryCSS, name, content.rules, level + 1, options); | ||
processSelectors(mediaQueryCSS, name, content.selectors, level + 1, options); | ||
processRules(mediaQueryCSS, name, content.rules, level + 1, parent, options); | ||
processSelectors(mediaQueryCSS, name, content.selectors, level + 1, parent, options); | ||
@@ -90,0 +109,0 @@ if (mediaQueryCSS.length) { |
@@ -31,9 +31,10 @@ 'use strict'; | ||
function transformStyleSheetObjectIntoSpecification(content) { | ||
var styles = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var parent = arguments[2]; | ||
assertPlainObject(content); | ||
var styles = {}; | ||
(0, _foreach2.default)(content, function (value, key) { | ||
if (isMediaQueryDeclaration.test(key)) { | ||
processMediaQuery(styles, key.substring(1), value); | ||
processMediaQuery(styles, key.substring(1), value, parent); | ||
} else if (isStandaloneSelector.test(key)) { | ||
@@ -49,5 +50,14 @@ (0, _assert2.default)(false, 'stand-alone selectors are not allowed at the top-level'); | ||
processStyleAndSelector(styles, styleName, selectorName, value); | ||
processStyleAndSelector(styles, styleName, selectorName, value, parent); | ||
} else if (key.charAt(0) === '$') { | ||
var firstSubKey = Object.keys(value)[0]; | ||
if (!isPlainObject(value[firstSubKey])) { | ||
// needs to be deprecated | ||
processStyle(styles, key, value); | ||
} else { | ||
transformStyleSheetObjectIntoSpecification(value, styles, key.substring(1)); | ||
} | ||
} else { | ||
processStyle(styles, key, value); | ||
processStyle(styles, key, value, parent); | ||
} | ||
@@ -59,3 +69,3 @@ }); | ||
function processMediaQuery(styles, mediaQueryName, content) { | ||
function processMediaQuery(styles, mediaQueryName, content, parent) { | ||
assertPlainObject(content); | ||
@@ -76,5 +86,5 @@ | ||
processStyleAndMediaQueryAndSelector(styles, styleName, mediaQueryName, selectorName, value); | ||
processStyleAndMediaQueryAndSelector(styles, styleName, mediaQueryName, selectorName, value, parent); | ||
} else { | ||
processStyleAndMediaQuery(styles, key, mediaQueryName, value); | ||
processStyleAndMediaQuery(styles, key, mediaQueryName, value, parent); | ||
} | ||
@@ -84,12 +94,12 @@ }); | ||
function processStyle(styles, styleName, content) { | ||
function processStyle(styles, styleName, content, parent) { | ||
assertPlainObject(content); | ||
var style = initStyleSpec(styles, styleName); | ||
var style = initStyleSpec(styles, styleName, parent); | ||
(0, _foreach2.default)(content, function (value, key) { | ||
if (isMediaQueryDeclaration.test(key)) { | ||
processStyleAndMediaQuery(styles, styleName, key.substring(1), value); | ||
processStyleAndMediaQuery(styles, styleName, key.substring(1), value, parent); | ||
} else if (isStandaloneSelector.test(key)) { | ||
processStyleAndSelector(styles, styleName, key, value); | ||
processStyleAndSelector(styles, styleName, key, value, parent); | ||
} else if (hasAttachedSelector.test(key)) { | ||
@@ -103,6 +113,6 @@ (0, _assert2.default)(false, 'styles cannot be nested into each other'); | ||
function processStyleAndMediaQuery(styles, styleName, mediaQueryName, content) { | ||
function processStyleAndMediaQuery(styles, styleName, mediaQueryName, content, parent) { | ||
assertPlainObject(content); | ||
var style = initStyleSpec(styles, styleName); | ||
var style = initStyleSpec(styles, styleName, parent); | ||
var mediaQuery = initMediaQuerySpec(style.mediaQueries, mediaQueryName); | ||
@@ -114,3 +124,3 @@ | ||
} else if (isStandaloneSelector.test(key)) { | ||
processStyleAndMediaQueryAndSelector(styles, styleName, mediaQueryName, key, value); | ||
processStyleAndMediaQueryAndSelector(styles, styleName, mediaQueryName, key, value, parent); | ||
} else if (hasAttachedSelector.test(key)) { | ||
@@ -124,6 +134,6 @@ (0, _assert2.default)(false, 'styles cannot be nested into each other'); | ||
function processStyleAndSelector(styles, styleName, selectorName, content) { | ||
function processStyleAndSelector(styles, styleName, selectorName, content, parent) { | ||
assertPlainObject(content); | ||
var style = initStyleSpec(styles, styleName); | ||
var style = initStyleSpec(styles, styleName, parent); | ||
var selector = initSelectorSpec(style.selectors, selectorName); | ||
@@ -144,6 +154,6 @@ | ||
function processStyleAndMediaQueryAndSelector(styles, styleName, mediaQueryName, selectorName, content) { | ||
function processStyleAndMediaQueryAndSelector(styles, styleName, mediaQueryName, selectorName, content, parent) { | ||
(0, _assert2.default)(isPlainObject(content), 'style value must be a plain object'); | ||
var style = initStyleSpec(styles, styleName); | ||
var style = initStyleSpec(styles, styleName, parent); | ||
var mediaQuery = initMediaQuerySpec(style.mediaQueries, mediaQueryName); | ||
@@ -170,6 +180,13 @@ var selector = initSelectorSpec(mediaQuery.selectors, selectorName); | ||
function initStyleSpec(styles, name) { | ||
function initStyleSpec(styles, name, parent) { | ||
(0, _assert2.default)(isValidStyleName.test(name), 'style name is invalid: ' + name); | ||
styles[name] = styles[name] || { rules: {}, selectors: {}, mediaQueries: {} }; | ||
if (parent) { | ||
styles[name].parents = styles[name].parents || {}; | ||
return initStyleSpec(styles[name].parents, parent); | ||
} | ||
return styles[name]; | ||
@@ -176,0 +193,0 @@ } |
{ | ||
"name": "babel-plugin-css-in-js", | ||
"version": "1.4.1", | ||
"version": "1.5.0", | ||
"description": "A plugin for Babel v6 which transforms inline styles defined in JavaScript modules into class names so they become available to, e.g. the `className` prop of React elements. While transforming, the plugin processes all JavaScript style definitions found and bundles them up into a CSS file, ready to be requested from your web server.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -10,3 +10,3 @@ # babel-plugin-css-in-js | ||
babel-plugin-css-in-js works seamlessly on both client and server. It has built-in support for media queries, pseudo-classes, and attribute selectors. The plugin's options allow you to configure vendor-prefixing, minification, and class name compression. | ||
babel-plugin-css-in-js works seamlessly on both client and server. It has built-in support for media queries, pseudo-classes, attribute selectors, and theming. The plugin's options allow you to configure vendor-prefixing, minification, and class name compression. | ||
@@ -307,2 +307,40 @@ If you're impatient, [visit the live demo](http://babel-plugin-css-in-js.martinandert.com/). The source code for it can be found [in the example directory](example/). | ||
**Basic theming via nesting within global selectors** | ||
You can nest your styles within another selector which is prefixed with `$`. These "global" selectors will be prepended (without the dollar sign of course) to the styles when generating the CSS. Nested styles also support pseudo-classes, attribute selectors and media queries. Example: | ||
```js | ||
{ | ||
myButton: { | ||
color: 'black' | ||
}, | ||
'$body.red-theme': { | ||
myButton: { | ||
color: 'red' | ||
} | ||
}, | ||
'$.blue >': { | ||
myButton: { | ||
color: 'blue'; | ||
} | ||
} | ||
} | ||
``` | ||
CSS output (assuming `b1` will become the generated class name for `myButton`): | ||
```css | ||
.b1 { | ||
color: black; | ||
} | ||
body.red-theme .b1 { | ||
color: red; | ||
} | ||
.blue > .b1 { | ||
color: blue; | ||
} | ||
``` | ||
**Global Styles** | ||
@@ -309,0 +347,0 @@ |
55252
772
493