Skip to content

Commit 57a2fe4

Browse files
authored
Merge pull request #1 from nealgranger/array-parser-support
Support for named exports and arrays.
2 parents 6978526 + 904b127 commit 57a2fe4

File tree

1 file changed

+94
-22
lines changed

1 file changed

+94
-22
lines changed

index.js

Lines changed: 94 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
var defaults = require('lodash/defaults');
2+
var mapKeys = require('lodash/mapKeys');
3+
var isArray = require('lodash/isArray');
4+
var omit = require('lodash/omit');
5+
var isString = require('lodash/isString');
6+
var isNumber = require('lodash/isNumber');
27
var loaderUtils = require('loader-utils');
38
var dangerousStyleValue = require('react/lib/dangerousStyleValue');
49
var hyphenateStyleName = require('fbjs/lib/hyphenateStyleName');
@@ -15,38 +20,69 @@ function line(pretty) {
1520
return pretty ? '\n' : '';
1621
}
1722

18-
function parse(config, styles, level) {
19-
level = level === undefined ? 0 : level;
23+
function isProp(value) {
24+
return isArray(value) ?
25+
isProp(value[0], true) :
26+
isString(value) || isNumber(value);
27+
}
28+
29+
function format(config, value, name, level, inProp) {
30+
level = level !== undefined ? level : 0;
2031

2132
var pretty = config.pretty;
2233
var css = '';
34+
var indentLevel = level;
2335

24-
for (var styleName in styles) {
25-
if (!styles.hasOwnProperty(styleName)) {
26-
continue;
36+
if (isArray(value)) {
37+
for (var i = 0, len = value.length; i < len; i ++) {
38+
css += format(config, value[i], name, level, inProp);
2739
}
40+
return css;
41+
}
2842

29-
// Extract the style definition or nested block.
30-
var styleValue = styles[styleName];
31-
32-
if (styleValue === null) {
33-
continue;
43+
if (inProp) {
44+
// The `name` and `value` args currently represent a css property and value.
45+
// Use React's css style processing funcs to generate css markup.
46+
47+
css += indent(pretty, indentLevel) + hyphenateStyleName(name) + ':' + space(pretty);
48+
css += dangerousStyleValue(name, value) + ';' + line(pretty);
49+
} else {
50+
// The `name` and `value` args currently represent a block containing css
51+
// properties or further nested blocks. Iterate through and parse
52+
// the nested values.
53+
54+
if (name) {
55+
// Unless we are in the global css scope (`name` is undefined), add a new
56+
// block to the markup.
57+
css += indent(pretty, indentLevel) + name + space(pretty) + '{' + line(pretty);
58+
indentLevel += 1;
3459
}
3560

36-
// Remove whitespace from selector/block.
37-
styleName = styleName.trim();
61+
for (var key in value) {
62+
if (!value.hasOwnProperty(key)) {
63+
continue;
64+
}
3865

39-
var block = Object.prototype.toString.call(styleValue) === '[object Object]';
66+
// Extract the style definition or nested block.
67+
var innerValue = value[key];
4068

41-
if (block) {
42-
css += indent(pretty, level) + styleName + space(pretty) + '{' + line(pretty);
43-
css += parse(config, styleValue, level + 1);
44-
css += indent(pretty, level) + '}' + line(pretty) + line(pretty);
45-
continue;
69+
if (innerValue === null) {
70+
continue;
71+
}
72+
73+
// Determine if the inner value is a block or a property.
74+
var innerIsProp = isProp(innerValue);
75+
76+
// Remove whitespace from selector/block/property.
77+
var innerName = key.trim();
78+
79+
css += format(config, innerValue, innerName, level + 1, innerIsProp);
4680
}
4781

48-
css += indent(pretty, level + 1) + hyphenateStyleName(styleName) + ':' + space(pretty);
49-
css += dangerousStyleValue(styleName, styleValue) + ';' + line(pretty);
82+
if (name) {
83+
// Close the open block.
84+
css += indent(pretty, level) + '}' + line(pretty) + line(pretty);
85+
}
5086
}
5187

5288
return css;
@@ -55,9 +91,45 @@ function parse(config, styles, level) {
5591
module.exports = function(content) {
5692
this.cacheable();
5793

58-
config = defaults(loaderUtils.getLoaderConfig(this, 'jsCssLoader'), {pretty: process.env.NODE_ENV !== 'production'});
94+
config = defaults(
95+
loaderUtils.getLoaderConfig(this, 'jsCssLoader'),
96+
{pretty: process.env.NODE_ENV !== 'production'}
97+
);
5998

6099
var styles = this.exec(content, this.resourcePath);
61100

62-
return parse(config, styles.__esModule ? styles.default : styles);
101+
var css = '';
102+
103+
if (styles.__esModule) {
104+
// When using Babel, css classes can be defined as named es6 exports.
105+
//
106+
// e.x.
107+
//
108+
// ```
109+
// export default {
110+
// '.base': {
111+
// color: 'black'
112+
// }
113+
// };
114+
// ```
115+
//
116+
// is the same as
117+
//
118+
// ```
119+
// export const base = {
120+
// color: 'black'
121+
// };
122+
// ```
123+
return format(config, [
124+
styles.default,
125+
mapKeys(
126+
omit(styles, 'default'),
127+
function (value, key) {
128+
return '.' + key;
129+
}
130+
),
131+
]);
132+
}
133+
134+
return format(config, styles);
63135
};

0 commit comments

Comments
 (0)