Supporting nested maps?
jeaster12 opened this issue · comments
Hi All!
I'm wondering if there are some further examples of custom formatters? I'm attempting to support nested sass maps easier and haven't found a great solution.
For instance given:
props:
- name: primary
value:
0: "#e8f7ff"
1: "#ccedff"
2: "#a3daff"
- name: success
value:
0: "#ebfbee"
1: "#d3f9d8"
2: "#b2f2bb"
I could get something like:
$color-map: (
'primary': (
0: "#e8f7ff"
1: "#ccedff"
2: "#a3daff"
),
'success': (
0: "#ebfbee"
1: "#d3f9d8"
2: "#b2f2bb"
),
) !default;
Perhaps with the option to return a variables map?:
$color-map: (
'primary': (
0: "$brand-primary-0"
1: "$brand-primary-1"
2: "$brand-primary-2"
),
'success': (
0: "$brand-success-0"
1: "$brand-success-1"
2: "$brand-success-2"
),
) !default;
Thanks for any guidance!
Hey @jeaster12 you can try something like this for a custom format:
//test.format.js
const { Map } = require('immutable');
module.exports = theo => {
theo.registerFormat('nested.map.scss', raw => {
const props = raw.get('props');
const data = props.map(prop => {
const value = prop.get('value');
if (Map.isMap(value)) {
const name = prop.get('name');
return {
name,
value: value.toObject()
};
} else {
return value;
}
});
const map = data.toArray().map(d => {
const body = Object.keys(d.value).map(k => `${k}: ${d.value[k]}`);
return `'${d.name}': ( ${body} )`;
});
return `$color-map: ( ${map.join('\n')} ) !default`;
});
};
and then can run it from the CLI like so:
theo --setup test.format.js test2.yaml --format nested.map.scss --dest output
Let me know if this works for you
@trazek thanks! this is a great help! Is it also possible to return the map with variables?
$color-map: (
'primary': (
0: "$brand-primary-0"
1: "$brand-primary-1"
2: "$brand-primary-2"
),
'success': (
0: "$brand-success-0"
1: "$brand-success-1"
2: "$brand-success-2"
),
) !default;
Well you can make const body = Object.keys(d.value).map(k =>
${k}: ${d.value[k]});
return whatever string you want. If you make it return $brand-primary-0
, etc, it's not really formatting the token data however. This being a custom format, you are free to return the structure you desire and also return the mapping for $brand-primary-0, 1, 2
etc.
If I have time, I can create an example of what I mean but let me know if you get the gist.
Cheers
Perfect I got it figured out! Thanks again.
Is there a way to keep the platform specific type conversions with lists and maps? For example, given a map of colors
global:
category: colors
type: color
imports:
- ../aliases/colors.yml
props:
colors:
value:
primary: "{!blue}"
secondary: "{!red}"
Theo will try to convert the map to a color and the result will be colors: "rgb(0, 0, 0)"
, when the target is web, instead of a map of colors.
Maybe a recursive definition for props would allow setting the type for any key. Although that ends up being quite verbose and allowing polymorphic types is questionable. A better option may be to add a new leafType
option, that specifies the type of the leaf nodes.
I was able to do what I wanted using meta data and a custom formatter without too much difficulty. Still, it would be nice to declaratively represent the shape of the design tokens in a config file and not have to write a custom formatter to reshape them.