-
-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathobjectifier.js
More file actions
116 lines (105 loc) · 2.91 KB
/
objectifier.js
File metadata and controls
116 lines (105 loc) · 2.91 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
107
108
109
110
111
112
113
114
115
116
let UNITLESS = {
boxFlex: true,
boxFlexGroup: true,
columnCount: true,
flex: true,
flexGrow: true,
flexPositive: true,
flexShrink: true,
flexNegative: true,
fontWeight: true,
lineClamp: true,
lineHeight: true,
opacity: true,
order: true,
orphans: true,
tabSize: true,
widows: true,
zIndex: true,
zoom: true,
fillOpacity: true,
strokeDashoffset: true,
strokeOpacity: true,
strokeWidth: true
}
function atRule(node) {
return node.nodes === undefined ? true : process(node)
}
// From https://github.com/hyperz111/fast-camelcase-css
function camelcase(property) {
property = property.toLowerCase()
if (property === 'float') return 'cssFloat'
let index = property.indexOf('-')
// Early return if don't have a dash
if (index === -1) return property
// Microsoft vendor-prefixes are uniquely cased
if (property.startsWith('-ms-')) {
property = property.slice(1)
index = property.indexOf('-')
}
let cursor = 0
let result = ''
do {
result += property.slice(cursor, index) + property[index + 1].toUpperCase()
cursor = index + 2
index = property.indexOf('-', cursor)
} while (index !== -1)
return result + property.slice(cursor)
}
function process(node, options = {}) {
let name
let result = {}
node.each(child => {
if (child.type === 'atrule') {
name = '@' + child.name
if (child.params) name += ' ' + child.params
if (result[name] === undefined) {
result[name] = atRule(child)
} else if (Array.isArray(result[name])) {
result[name].push(atRule(child))
} else {
result[name] = [result[name], atRule(child)]
}
} else if (child.type === 'rule') {
let body = process(child)
if (result[child.selector]) {
for (let i in body) {
let object = result[child.selector]
if (
options.stringifyImportant &&
typeof object[i] === 'string' &&
object[i].endsWith('!important')
) {
if (typeof body[i] === 'string' && body[i].endsWith('!important')) {
object[i] = body[i]
}
} else {
object[i] = body[i]
}
}
} else {
result[child.selector] = body
}
} else if (child.type === 'decl') {
if (child.prop.startsWith('--')) {
name = child.prop
} else if (child.parent && child.parent.selector === ':export') {
name = child.prop
} else {
name = camelcase(child.prop)
}
let value = child.value
if (!isNaN(child.value) && UNITLESS[name]) value = parseFloat(child.value)
if (child.important) value += ' !important'
if (result[name] === undefined) {
result[name] = value
} else if (Array.isArray(result[name])) {
result[name].push(value)
} else {
result[name] = [result[name], value]
}
}
})
return result
}
module.exports = process