|
1 | 1 | import _ from 'lodash'
|
2 |
| -import functions from 'postcss-functions' |
3 | 2 | import didYouMean from 'didyoumean'
|
4 | 3 | import transformThemeValue from '../util/transformThemeValue'
|
| 4 | +import parseValue from 'postcss-value-parser' |
5 | 5 |
|
6 | 6 | function findClosestExistingPath(theme, path) {
|
7 | 7 | const parts = _.toPath(path)
|
@@ -109,23 +109,70 @@ function validatePath(config, path, defaultValue) {
|
109 | 109 | }
|
110 | 110 | }
|
111 | 111 |
|
| 112 | +function extractArgs(node, vNodes, functions) { |
| 113 | + vNodes = vNodes.map((vNode) => resolveVNode(node, vNode, functions)) |
| 114 | + |
| 115 | + let args = [''] |
| 116 | + |
| 117 | + for (let vNode of vNodes) { |
| 118 | + if (vNode.type === 'div' && vNode.value === ',') { |
| 119 | + args.push('') |
| 120 | + } else { |
| 121 | + args[args.length - 1] += parseValue.stringify(vNode) |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + return args |
| 126 | +} |
| 127 | + |
| 128 | +function resolveVNode(node, vNode, functions) { |
| 129 | + if (vNode.type === 'function' && functions[vNode.value] !== undefined) { |
| 130 | + let args = extractArgs(node, vNode.nodes, functions) |
| 131 | + vNode.type = 'word' |
| 132 | + vNode.value = functions[vNode.value](node, ...args) |
| 133 | + } |
| 134 | + |
| 135 | + return vNode |
| 136 | +} |
| 137 | + |
| 138 | +function resolveFunctions(node, input, functions) { |
| 139 | + return parseValue(input) |
| 140 | + .walk((vNode) => { |
| 141 | + resolveVNode(node, vNode, functions) |
| 142 | + }) |
| 143 | + .toString() |
| 144 | +} |
| 145 | + |
| 146 | +let nodeTypePropertyMap = { |
| 147 | + atrule: 'params', |
| 148 | + decl: 'value', |
| 149 | +} |
| 150 | + |
112 | 151 | export default function (config) {
|
113 |
| - return (root) => |
114 |
| - functions({ |
115 |
| - functions: { |
116 |
| - theme: (path, ...defaultValue) => { |
117 |
| - const { isValid, value, error } = validatePath( |
118 |
| - config, |
119 |
| - path, |
120 |
| - defaultValue.length ? defaultValue : undefined |
121 |
| - ) |
122 |
| - |
123 |
| - if (!isValid) { |
124 |
| - throw root.error(error) |
125 |
| - } |
126 |
| - |
127 |
| - return value |
128 |
| - }, |
129 |
| - }, |
130 |
| - })(root) |
| 152 | + let functions = { |
| 153 | + theme: (node, path, ...defaultValue) => { |
| 154 | + const { isValid, value, error } = validatePath( |
| 155 | + config, |
| 156 | + path, |
| 157 | + defaultValue.length ? defaultValue : undefined |
| 158 | + ) |
| 159 | + |
| 160 | + if (!isValid) { |
| 161 | + throw node.error(error) |
| 162 | + } |
| 163 | + |
| 164 | + return value |
| 165 | + }, |
| 166 | + } |
| 167 | + return (root) => { |
| 168 | + root.walk((node) => { |
| 169 | + let property = nodeTypePropertyMap[node.type] |
| 170 | + |
| 171 | + if (property === undefined) { |
| 172 | + return |
| 173 | + } |
| 174 | + |
| 175 | + node[property] = resolveFunctions(node, node[property], functions) |
| 176 | + }) |
| 177 | + } |
131 | 178 | }
|
0 commit comments