Remove dependency on postcss-functions (#4317)

* Write postcss-functions ourselves

* Add test for nested theme calls

* Remove unused import
This commit is contained in:
Adam Wathan 2021-05-11 14:33:05 -04:00 • committed by GitHub
parent 522787ac41
commit 5ebe5e8309
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 19 deletions

View file

@ -1,7 +1,7 @@
import _ from 'lodash'
import functions from 'postcss-functions'
import didYouMean from 'didyoumean'
import transformThemeValue from '../util/transformThemeValue'
import parseValue from 'postcss-value-parser'
function findClosestExistingPath(theme, path) {
const parts = _.toPath(path)
@ -109,23 +109,70 @@ function validatePath(config, path, defaultValue) {
}
}
export default function (config) {
return (root) =>
functions({
functions: {
theme: (path, ...defaultValue) => {
const { isValid, value, error } = validatePath(
config,
path,
defaultValue.length ? defaultValue : undefined
)
function extractArgs(node, vNodes, functions) {
vNodes = vNodes.map((vNode) => resolveVNode(node, vNode, functions))
if (!isValid) {
throw root.error(error)
}
let args = ['']
return value
},
},
})(root)
for (let vNode of vNodes) {
if (vNode.type === 'div' && vNode.value === ',') {
args.push('')
} else {
args[args.length - 1] += parseValue.stringify(vNode)
}
}
return args
}
function resolveVNode(node, vNode, functions) {
if (vNode.type === 'function' && functions[vNode.value] !== undefined) {
let args = extractArgs(node, vNode.nodes, functions)
vNode.type = 'word'
vNode.value = functions[vNode.value](node, ...args)
}
return vNode
}
function resolveFunctions(node, input, functions) {
return parseValue(input)
.walk((vNode) => {
resolveVNode(node, vNode, functions)
})
.toString()
}
let nodeTypePropertyMap = {
atrule: 'params',
decl: 'value',
}
export default function (config) {
let functions = {
theme: (node, path, ...defaultValue) => {
const { isValid, value, error } = validatePath(
config,
path,
defaultValue.length ? defaultValue : undefined
)
if (!isValid) {
throw node.error(error)
}
return value
},
}
return (root) => {
root.walk((node) => {
let property = nodeTypePropertyMap[node.type]
if (property === undefined) {
return
}
node[property] = resolveFunctions(node, node[property], functions)
})
}
}