-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathcssToJss.js
More file actions
106 lines (98 loc) · 2.94 KB
/
cssToJss.js
File metadata and controls
106 lines (98 loc) · 2.94 KB
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const css = require('css')
const camelCase = require('lodash/camelCase')
/**
* Convert css to jss.
*
* @param {Object} options
* @return {Object}
* @api public
*/
module.exports = function (options) {
const ast = css.parse(options.code)
let styles = {}
if (ast.stylesheet && ast.stylesheet.rules) {
styles = toJssRules(ast.stylesheet.rules, options)
}
return styles
}
/**
* Convert rules from css ast to jss style.
*
* @param {Array} cssRules
* @param {Object} options
* @return {Object}
*/
function toJssRules(cssRules, options) {
const jssRules = {}
function stripUnit(value) {
if (
!options.unit ||
// Detect a compound/multi value.
/\s|,/.test(value)
) return value
const unit = value.substr(value.length - options.unit.length)
const num = parseFloat(value)
if (unit === options.unit && num !== NaN) {
return num
}
return value
}
function addRule(rule, rules) {
if (rule.type === 'comment') return
const key = rule.type === 'page' ? '@page ' + rule.selectors.join(', ') : rule.selectors.join(', ')
const style = rules[key] || (rules[key] = {})
rule.declarations.forEach(function (decl) {
if (decl.type === 'comment') return
const property = formatProp(decl.property)
if (property in style) {
const fallbacks = style.fallbacks || (style.fallbacks = [])
fallbacks.splice(0, 0, { [property]: style[property] })
}
style[property] = stripUnit(decl.value)
})
}
function formatProp(prop) {
// Capitalize the first character
return options.dashes ? prop : (typeof prop === 'string' && prop.substring(0, 1) === '-') ?
camelCase(prop).charAt(0).toUpperCase() : camelCase(prop)
}
cssRules.forEach(function (rule) {
if (rule.type === 'comment') return
switch (rule.type) {
case 'rule':
addRule(rule, jssRules)
break
case 'page':
addRule(rule, jssRules)
break
case 'media': {
const key = '@media ' + rule.media
const value = jssRules[key] || (jssRules[key] = {})
rule.rules.forEach(function(rule) {
addRule(rule, value)
})
break
}
case 'font-face': {
const key = '@' + rule.type
const value = jssRules[key] || (jssRules[key] = {})
rule.declarations.forEach(function (decl) {
value[formatProp(decl.property)] = decl.value
})
break
}
case 'keyframes': {
const key = '@' + rule.type + ' ' + rule.name
const value = jssRules[key] || (jssRules[key] = {})
rule.keyframes.forEach(function (keyframe) {
const frameKey = keyframe.values.join(', ')
const frameValue = value[frameKey] || (value[frameKey] = {})
keyframe.declarations.forEach(function (decl) {
frameValue[formatProp(decl.property)] = stripUnit(decl.value)
})
})
}
}
})
return {'@global': jssRules}
}