tokens-studio / sd-transforms

Custom transforms for Style-Dictionary, to work with Design Tokens that are exported from Tokens Studio
MIT License
194 stars 28 forks source link

[Bug]: Transforming kebab-case key names to camelCase does not seem to work #239

Closed fwielstra closed 3 months ago

fwielstra commented 9 months ago

What happened?

In the source tokens there's a few keys in kebab-case, which we'd like to convert to camelCase in the output.

I believe the documentation says that it's a matter of setting the casing option to camel, but this does not seem to work.

I've also tried to use a custom name transformation that detects and converts the name, but maybe I'm missing something obvious or small.

Reproduction

The transforms and configuration that I use:

StyleDictionary.registerTransform({
  name: "my/kebabToCamelCase",
  type: "name",
  transitive: true,
  matcher: (token) => {
    return token.name.includes("-");
  },
  transformer: (token) => {
    return token.name.replace(/-./g, (x) => x[1].toUpperCase());
  },
});

registerTransforms(StyleDictionary, {
  casing: "camel",
});

// Register custom tokens-studio transform group
// https://github.com/tokens-studio/sd-transforms?tab=readme-ov-file#custom-transform-group
StyleDictionary.registerTransformGroup({
  name: "custom/react-native",
  transforms: [...transforms, "my/kebabToCamelCase"],
});

Using the power of console.log in the matcher and transformer functions, I can see that keys like text-case, border-radius andsoforth are converted to textCase and borderRadius, however, the output JSON still retains the existing kebab-case:

Input exertpt:

    "typography": {
      "text-case": {
        "none": {
          "value": "none",
          "type": "textCase"
        },
        "uppercase": {
          "value": "uppercase",
          "type": "textCase"
        },
        "lowercase": {
          "value": "lowercase",
          "type": "textCase"
        },
        "capitalize": {
          "value": "capitalize",
          "type": "textCase"
        }
      },
      "text-decoration": {
        "none": {
          "value": "none",
          "type": "textDecoration"
        },
        "underline": {
          "value": "underline",
          "type": "textDecoration"
        },
        "line-through": {
          "value": "line-through",
          "type": "textDecoration"
        }
      }
    }

Output exerpt:

    "typography": {
      "text-case": {
        "none": "none",
        "uppercase": "uppercase",
        "lowercase": "lowercase",
        "capitalize": "capitalize"
      },
      "text-decoration": {
        "none": "none",
        "underline": "underline",
        "line-through": "line-through"
      }
    }

Expected output

    "typography": {
      "textCase": {
        "none": "none",
        "uppercase": "uppercase",
        "lowercase": "lowercase",
        "capitalize": "capitalize"
      },
      "textDecoration": {
        "none": "none",
        "underline": "underline",
        "lineThrough": "line-through"
      }
    }

Version

0.11.10

jorenbroekema commented 9 months ago

What format are you using for the output? javascript/object perhaps?

Some of the formats seem to just JSON.stringify() the dictionary and not take into account the name of the token at all, so even if name transforms apply, the output won't care about them.

This isn't a sd-transforms issue though but rather a style-dictionary issue, could you create an issue there? I think the solution is to give the JSON.stringify methods a replacer function that alters the keys to the token name if such a prop exists. Preferably for all of the formats that use this type of approach for writing the output. It would be a breaking change but since I'm working on v4 I'd be down to include it in v4

jorenbroekema commented 3 months ago

Closed due to inactivity and no follow up on the SD repo.