Allow "filter" option in config file to support array of objects
See original GitHub issueCalling in @elliotdickison here, since you worked on #101. In the documentation we say that:
platform.file.filter | Function/Object (optional) | A function or object used to filter the properties that will be included in the file. If a function is provided, each property will be passed to the function and the result (true or false) will determine whether the property is included. If an object is provided, each property will be matched against the object using a partial deep comparison to determine whether the property is included.
But if the config is a JSON file, there is no way to pass a function to the filter
property (maybe we should update the documentation?), so the only way to apply a filter is via an object:
"filter": {
"attributes": {
"category": "color"
}
}
which in the code is transformed to a matching filter function via the Lodash matches
method:
const filterFunc = _.isFunction(filter) ? filter : _.matches(filter)
This also means we can filter only for one CTI property (eg. color, or size) at the time. In reality often is useful to have a filter that can work with multiple CTI properties (eg. “give me all the color and size properties”) but as is now is not possible.
What I am proposing here is to extend a little bit the capabilities of the filter, and accept an array of objects. Something like this:
"filter": [{
"attributes": {
"category": "size"
}
},{
"attributes": {
"category": "color"
}
}]
where the filterProperties
function would look something like this (notice: the array filter function is probably wrong, I have to investigate what is the correct way to write it, but it gives you a gist of what I mean):
function filterProperties(dictionary, filter) {
if (!filter) {
return dictionary
} else {
let filterFunc;
if (_.isFunction(filter)) {
filterFunc = filter;
} else if (_.isArray(filter) && filter.every(_.isObject(filter))) {
filterFunc = function (filter) {
return filter.some(function(obj) { return _.matches(filter); });
};
} else if (_.isObject(filter)) {
filterFunc = _.matches(filter);
} else {
// maybe throw an error here?
}
return _.assign({}, dictionary, {
allProperties: filterPropertyArray(dictionary.allProperties, filterFunc),
properties: filterPropertyObject(dictionary.properties, filterFunc)
})
}
}
What do you think of this? Adding too much complexity? (pinging @dbanksdesign + @chazzmoney if they have some ideas/comments)
Issue Analytics
- State:
- Created 5 years ago
- Comments:9 (7 by maintainers)
Looks like this is getting complex (the multiple options, the negation, the OR vs AND). The risk is to take something that works and it’s “easy” to use and convert it to something too complex and unpredictable. What do you think if instead we define a new
registerFilter
method in Style Dictionary (similar to what we have withregisterFormat
,registerTemplate
,registerAction
) so that we can do:(in the same way as we do
"template": "name_of_template"
or"format": "name_of_format"
).Then in the
filterProperties
function declaration we can easily detect if the filter is a “custom” filter by the fact that is a string.Forgot to add: this is motivated by https://github.com/amzn/style-dictionary/pull/164#issuecomment-438219133