如何将 json 转换为 style-dictionary 中的 css 类?

Sri*_*Sri 1 css json styles token style-dictionary

我有以下button.json

{
  "component": {
  "button": {
    "padding": { "value": "{size.padding.medium.value}" },
    "font-size": { "value": 2 },
    "text-align": { "value": "center" },
  
    "primary": {
      "background-color": { "value": "hsl(10, 80, 50)" },
      "color": { "value": "{color.font.inverse.value}" }
    },
  
    "secondary": {
      "background-color": { "value": "{color.background.primary.value}" },
      "color": { "value": "{color.font.link.value}" }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以使用亚马逊样式字典生成样式标记。我想要生成的是 json 中的完整 sass css。

例如:

.component-button {

    padding: " ";
    font-size: " ";

    & .primary {
        background-color: "",
        color: ""
    }
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ser 5

一种方法是使用自定义模板创建自定义格式来呈现文件.scss。I\xe2\x80\x99ve 包含了执行此操作的基本代码如下。

\n

首先,这是我使用的button.json文件:

\n
{\n  "color": {\n    "background": {\n      "primary": { "value": "hsl(10, 80, 50)" },\n      "secondary": { "value": "hsl(10, 80, 90)" }\n    },\n    "font": {\n      "inverse": { "value": "#fff" },\n      "link": { "value": "#00f" }\n    }\n  },\n  "size": {\n    "2": { "value": 16 },\n    "padding": {\n      "medium": { "value": 16 }\n    }\n  },\n  "component": {\n    "button": {\n      "padding": { "value": "{size.padding.medium.value}" },\n      "font-size": { "value": "{size.2.value}" },\n      "text-align": { "value": "center" },\n      "primary": {\n        "background-color": { "value": "{color.background.primary.value}" },\n        "color": { "value": "{color.font.inverse.value}" }\n      },\n      "secondary": {\n        "background-color": { "value": "{color.background.secondary.value}" },\n        "color": { "value": "{color.font.link.value}" }\n      }\n    }\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我添加了一个附加的colorandsize对象,以便指针可以正确解析。我还对您的代币的结构进行了一些假设(例如size.2font-size),但希望总体思路是清晰的。

\n

这是主要的 JavaScript 代码。我添加了一些评论来尝试解释一切。

\n
const _ = require(\'lodash\')\n\n/*\n  This is formatted oddly in order to get a nice final shape\n  in `button.scss`.\n\n  Essentially what the template is doing is looping through\n  the props object and outputting the top-level properties\n  as the parent classnames, then for each child props of\n  "classname" it looks to see if the child prop is an object,\n  if it is, then it outputs the Sass `&.` operator with the\n  child prop rule as the sub classname and then each child\n  prop of the value as the final CSS style rule and value.\n  If it\'s not an object then it outputs the rule and value\n  as the CSS style rule and value.\n*/\nconst template = _.template(`<% _.each(props, function(prop, classname) { %>.<%= classname %> {\n<% _.each(prop, (value, rule) => { %><% if (typeof value === \'object\') { %>  &.<%= rule %> {<% _.each(value, (subvalue, subrule) => { %>\n    <%= subrule %>: <%= subvalue %>;<% }) %>\n  }<% } else { %>  <%= rule %>: <%= value %>;<% } %>\n<% }) %><% }) %>}\n`)\n\nconst StyleDictionary = require(\'style-dictionary\')\n  .registerFormat({\n    name: \'scss/button\',\n    formatter: function(dictionary, config) {\n      /*\n        allProperties is an array containing all the matched\n        tokens based on the filter.\n      */\n      const { allProperties } = dictionary\n\n      /*\n        Set up an empty object to hold the final shape to pass\n        to the custom template.\n\n        After the allProperties.map(), props will look like this:\n        {\n          \'component-button\': {\n            padding: \'16px\',\n            \'font-size\': \'16px\',\n            \'text-align\': \'center\',\n            primary: { \'background-color\': \'#e63c19\', color: \'#ffffff\' },\n            secondary: { \'background-color\': \'#fad8d1\', color: \'#0000ff\' }\n          }\n        }\n      */\n      const props = {}\n\n      // go through properties and structure final props object\n      allProperties.map(prop => {\n        /*\n          Extract the attributes object created by the \'attribute/cti\'\n          transform and the transformed token value.\n        */\n        const { attributes, value } = prop\n\n        // extract attributes to build custom class and style rules\n        const { category, type, item, subitem } = attributes\n\n        // build main classname for .scss file\n        const classname = `${category}-${type}`\n\n        /*\n          Add to the props object if it doesn\'t already exist.\n          We run the check to see if the classname exists already as an\n          object property because in our case, `classname` will be the\n          same for each token object in allProperties because each token\n          is under the same category and type.\n        */\n        if (!props.hasOwnProperty(classname)) {\n          props[classname] = {}\n        }\n\n        /*\n          If the token object has a subitem, use the item as the subclass.\n          Run the same check to see if this particular subclass (item) has\n          been added yet.\n        */\n        if (subitem) {\n          if (!props[classname].hasOwnProperty(item)) {\n            props[classname][item] = {}\n          }\n\n          // add the subitem and value as final CSS rule\n          props[classname][item][subitem] = value\n        }\n        else {\n          // add the item as a CSS rule, not a subclass\n          props[classname][item] = value\n        }\n      })\n\n      /*\n        Pass the final `props` object to our custom template to render\n        the contents for the final button.scss file.\n      */\n      return template({ props })\n    }\n  })\n  .extend({\n    source: [\'button.json\'],\n    platforms: {\n      scss: {\n        buildPath: \'build/\',\n        transforms: [\n          \'attribute/cti\',  // setup attributes object\n          \'color/css\',      // transform color values to hex\n          \'name/cti/kebab\', // prevent name collisions\n          \'size/px\'         // transform size values to px\n        ],\n        files: [\n          {\n            destination: \'button.scss\',\n            format: \'scss/button\',\n            filter: {\n              attributes: {\n                category: \'component\',\n                type: \'button\'\n              }\n            }\n          }\n        ]\n      }\n    }\n  })\n\n// run Style Dictionary\nStyleDictionary.buildAllPlatforms()\n
Run Code Online (Sandbox Code Playgroud)\n

如果你运行这个,你应该得到一个最终文件(build/button.scss),如下所示:

\n
.component-button {\n  padding: 16px;\n  font-size: 16px;\n  text-align: center;\n  &.primary {\n    background-color: #e63c19;\n    color: #ffffff;\n  }\n  &.secondary {\n    background-color: #fad8d1;\n    color: #0000ff;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n