npm package: @historylab/design-tokens
Description: Design Tokens for the HistoryLab project
Author: Jiří Maha
Latest version: 0.3.0

# Design tokens
[Design tokens](https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421) are named entities that store visual design information. These are used in place of hard-coded values (such as hex values for color or pixels for spacing) in order to maintain a scalable, consistent system for UI development. They stand above all. They are the most fundamental level shared throughout the whole company.

Technically speaking, we store them as key/value pair in JSON files which can be used by anyone to generate variables for any language.

## Structure, notation, naming
The structure of token notation in JSON and the resulted token name is constructed like this: `category` + `sub-category` + `device` + `level`. Use dash (`-`) as a separator. 

### Example: Token notation in JSON
````json
{
  "font-size": {
    "sans-serif": {
      "mobile": [
        {
          "0": "1.625rem"
        }
      ]
    }
  } 
}
````

### Example: Token name
````
font-size-sans-serif-mobile-0
````

## Values
From negative values to positive ones where level `0` is always meant as the default value, negative levels (`-1`) is used for darker or smaller values, positive levels (`1`) are used for lighter or bigger values. All levels are stored as objetcs in an array, in JSON.

```json
{
"token": [
    {
      "-1": "smaller/darker token value"
    },
    {
      "0": "default token value"
    },
    {
      "1": "bigger/lighter token value"
    }
  ]
}
```

## How to use them?
Use recursive function to loop through all nested objects until you reach a string which is the token value. Example of such function to create variable names:

````javascript
/**
 * Variable name is constructed from all keys parent to the actual value.
 *
 * @param {object} data  Input data in the form of Object or JSON.
 * @param {string} symbol  Symbol used in styling languages for variable names.
 * @param {string} prefix  Operational variable to store the name of a token.
 *
 * @return {string} returnData   Resulted string of variable name and value pairs.
 */
function createVariables(data, symbol, prefix) {
  let returnData = '';

  prefix = prefix ? `${prefix}-` : '';

  for (let [key, value] of Object.entries(data)) {
    // if string
    if (typeof value === 'string') {
      returnData += `${symbol}${prefix + key}: ${value};
`;
    }
    // if another nested object
    else if (typeof value === 'object') {
      // if the nested object is an array
      // we need to use an array (of objects) to keep the order of items
      if (value.constructor.name == 'Array') {
        value.forEach(item => {
          returnData += createVariables(item, symbol, (prefix + key));
        });
      } else {
        returnData += createVariables(value, symbol, (prefix + key));
      }
    }
  }

  return returnData;
}
````

Then, you can simply store the return data into file with npm scripts:

```javascript
// create a LESS file
const less = () => {
  const code = createVariables(tokenData, '@');
  const lessFileName = tokenFileName.replace('.json', '.less');

  fs.writeFile(lessFileName, code, (err) => err ? console.log(err));
}

// run the function
less();
```