style-dictionary icon indicating copy to clipboard operation
style-dictionary copied to clipboard

Replacing and computing aliased values in custom format

Open moniuch opened this issue 2 years ago • 4 comments

I am on v3.0.2 and I am trying to get the transitive flag to work. My Figma Tokens file though contains ref aliases that start with a dollar sign, like so (assume JSON quoted properly):

{
  spacing: {
    base: {
      value: '4',
      type: 'spacing'
    },
    medium: {
      value: "$spacing.base * 1.5",
      type: spacing
    }
  }
}

Needless to say, the expected state would be to have the reference both replaced and computed.

I tried:

  • passing options containing regexp - to the file definition as well as on the platform root. From what I see is should flow down to the usesReference function
files: [
 transformGroup: 'css',
 format: 'css/variables',
 options: /^\$.+/   // also tried passing as a string
]
  • replacing the dollar sign if value contains one, in a formatter - replacing works but value is not unaliased

My config.js has the formatters (color/css, name/cti/kebab, attribute/cti) extended with transitive: true as in the transitive example.

Please correct me if my expectations are wrong.

moniuch avatar Sep 10 '21 16:09 moniuch

I'm wondering about how to resolve these $ references coming from Figma as well.

littlered avatar Sep 24 '21 03:09 littlered

I wrote a script to transform from Figma Tokens aliases style to Style Dictionary supported aliases style

function parsing(stringifiedJSON, dir) {
    let shouldAppend = false;
    let newText = '';

    for (let index = 0; index < stringifiedJSON.length; index++) {
        let textIterate = stringifiedJSON[index];
        if (textIterate === '$') {
            shouldAppend = true;
            newText = newText.concat('{');
        } else if (shouldAppend && (textIterate === ' '
            || textIterate === '"'
            || textIterate === ','
            || textIterate === ')')) {
            shouldAppend = false;
            newText = newText.concat('.value}');
            newText = newText.concat(textIterate);
        }
        else {
            newText = newText.concat(textIterate);
        }
    }

    fs.writeFile(dir, newText, function (err) {
        if (err) {
            console.log(err);
        }
    });
}

preckrasno avatar Sep 30 '21 12:09 preckrasno

@preckrasno Yes, of course the replacements have to be done. What this script does here can be also achieved using a formatter, but regardless - this only one part of the job. Then the referenced values may leave some expressions or calculations in place, such as "4 * 4", so you also need to run through eval-expr. Or use a fresh package token-transformer that does everything.

moniuch avatar Sep 30 '21 16:09 moniuch

Hi @moniuch! Sorry for the late reply, things have been quite busy. There are 2 issues as you point out:

  1. The reference syntax is different
  2. Style Dictionary does not currently support arithmetic in design tokens.

We can tackle these problems separately. The first is best suited for a custom parser. Parsers run before a file is read into Style Dictionary and can modify its contents before getting to Style Dictionary. You could write a custom parser to look for design token values with a '$' and use a regex to turn $spacing.base into {spacing.base}.

The second problem is a bit trickier, but I believe could be done with a custom transitive transform. You would need to do a bit of magic like split the value string by *, parseFloat both sides, and then multiply both sides. A transitive transform will run after the token's references have been resolved so at that point spacing.base will be 4.

dbanksdesign avatar Nov 04 '21 23:11 dbanksdesign