-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
66 lines (58 loc) · 2.05 KB
/
index.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
const postcss = require('postcss')
function toCamel(s) {
return s.replace(/-(.)/g, ([, c]) => c.toUpperCase())
}
function fussRule(obj) {
if (obj.className === undefined) return obj
const { className, prop, value, breakpoint = null } = obj
const rule = postcss.rule({ selector: `.${className}` })
.append({ prop, value })
if (!breakpoint) {
return rule
} else {
const mq = `screen and ${breakpoint}`
return postcss.atRule({ name: 'media', params: mq }).append(rule)
}
}
function fussGroup(rules) {
return postcss.root().append(rules)
}
function classToFuss(node) {
if (node.type !== 'rule') return node
const { selector, nodes: [firstChild] } = node
return {
className: selector.replace(/^\./, ''),
prop: firstChild.prop,
value: firstChild.value,
}
}
function fussToClasses(rule, fussFunctions) {
if (rule.nodes) rule.walk(buildFussWalker(fussFunctions))
const { params, nodes: children = [] } = rule
if (!params || !params.includes('(') || !params.endsWith(')'))
throw new Error(`FUSS: Malformed call: ${params}`)
const name = params.slice(0, params.indexOf('('))
const argsString = params.slice(params.indexOf('(') + 1, -1)
const args = argsString.split(/,\s?/).filter(Boolean)
const funcName = toCamel(name)
if (!fussFunctions.hasOwnProperty(funcName))
throw new Error(`FUSS: Func not existent: ${name}`)
const func = fussFunctions[funcName].bind(fussFunctions)
const childList = children.map(classToFuss)
const fussNodes = func(...args, childList).map(fussRule)
const res = fussGroup(fussNodes)
res.prepend(`/* ${params} */`)
return res
}
function buildFussWalker(fussFunctions) {
return function fussWalker(rule) {
if (rule.type === 'atrule' && rule.name === 'fuss') {
rule.replaceWith(fussToClasses(rule, fussFunctions))
}
}
}
module.exports = postcss.plugin('postcss-fuss', function (opts) {
return root => {
root.walk(buildFussWalker(opts.functions))
}
})