-
Notifications
You must be signed in to change notification settings - Fork 3
/
cssObject.js
68 lines (63 loc) · 1.83 KB
/
cssObject.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
const { Asset } = require("parcel-bundler");
const css = require("css");
const camelCase = require("camelcase");
class CssObjectAsset extends Asset {
constructor(name, pkg, options) {
super(name, pkg, options);
this.type = "css";
}
parse(source) {
var parsedStylesheet = css.parse(source).stylesheet;
this.code =
parsedStylesheet &&
parsedStylesheet.rules.reduce(reduceRulesToSelectors, {});
}
generate() {
// Send to JS bundler
return {
js: `module.exports = ${JSON.stringify(
JSON.parse(JSON.stringify(this.code))
)}`
};
}
}
module.exports = CssObjectAsset;
// Return `true` for an AST node with { type: 'rule' } and valid selectors
function isValidRule(rule) {
return !!(rule.type === "rule" && rule.selectors && rule.selectors.length);
}
// Return `true` for an AST node with { type: 'declaration' } and any property
function isValidDeclaration(declaration) {
return !!(
declaration.type === "declaration" &&
declaration.property &&
declaration.property.length
);
}
// Reduce a declaration node from the AST to a style object
function reduceDeclarationsToStyleObject(styleObj, declaration) {
if (!isValidDeclaration(declaration)) {
return styleObj;
}
var key = camelCase(declaration.property);
var value = declaration.value;
styleObj[key] = value;
return styleObj;
}
// Reduce a rule to a collection of selectors
function reduceRulesToSelectors(selectors, rule) {
if (!isValidRule(rule)) {
return selectors;
}
var styleObject = rule.declarations.reduce(
reduceDeclarationsToStyleObject,
{}
);
const newSelectors = rule.selectors.map(selector => {
return selector.replace(".", "");
});
newSelectors.forEach(selector => {
selectors[selector] = Object.assign({}, selectors[selector], styleObject);
});
return selectors;
}