Skip to content

Commit

Permalink
fix: evaluate math in complex token value types
Browse files Browse the repository at this point in the history
  • Loading branch information
jorenbroekema committed Apr 19, 2023
1 parent a25a1ff commit acd3ddb
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/perfect-ravens-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tokens-studio/sd-transforms': patch
---

Evaluate math expressions within complex value types like border, typography, shadow.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ const sd = StyleDictionary.extend({
'ts/descriptionToComment',
'ts/size/px',
'ts/opacity',
'ts/size/css/letterspacing',
'ts/size/lineheight',
'ts/type/fontWeight',
'ts/resolveMath',
'ts/size/css/letterspacing',
'ts/typography/css/shorthand',
'ts/border/css/shorthand',
'ts/shadow/css/shorthand',
Expand Down
2 changes: 1 addition & 1 deletion src/checkAndEvaluateMath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function parseAndReduce(expr: string): string {
return `${Number.parseFloat(evaluated.toFixed(3))}${unit ?? (hasPx ? 'px' : '')}`;
}

export function checkAndEvaluateMath(expr: string | undefined): number | string | undefined {
export function checkAndEvaluateMath(expr: string | undefined): string | undefined {
if (expr === undefined) {
return expr;
}
Expand Down
5 changes: 4 additions & 1 deletion src/css/transformBorder.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { checkAndEvaluateMath } from '../checkAndEvaluateMath.js';
import { transformDimension } from '../transformDimension.js';
import { transformHEXRGBaForCSS } from './transformHEXRGBa.js';

Expand All @@ -13,5 +14,7 @@ export function transformBorderForCSS(
return border;
}
const { color, width, style } = border;
return `${transformDimension(width)} ${style} ${transformHEXRGBaForCSS(color)}`;
return `${transformDimension(checkAndEvaluateMath(width))} ${style} ${transformHEXRGBaForCSS(
color,
)}`;
}
9 changes: 5 additions & 4 deletions src/css/transformShadow.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { checkAndEvaluateMath } from '../checkAndEvaluateMath.js';
import { transformDimension } from '../transformDimension.js';
import { transformHEXRGBaForCSS } from './transformHEXRGBa.js';

Expand All @@ -14,10 +15,10 @@ export function transformShadowForCSS(
}
let { x, y, blur, spread } = shadow;
const { color, type } = shadow;
x = transformDimension(x) as string;
y = transformDimension(y) as string;
blur = transformDimension(blur) as string;
spread = transformDimension(spread) as string;
x = transformDimension(checkAndEvaluateMath(x)) as string;
y = transformDimension(checkAndEvaluateMath(y)) as string;
blur = transformDimension(checkAndEvaluateMath(blur)) as string;
spread = transformDimension(checkAndEvaluateMath(spread)) as string;
return `${
type === 'innerShadow' ? 'inset ' : ''
}${x} ${y} ${blur} ${spread} ${transformHEXRGBaForCSS(color)}`;
Expand Down
11 changes: 7 additions & 4 deletions src/css/transformTypography.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { transformDimension } from '../transformDimension.js';
import { transformFontWeights } from '../transformFontWeights.js';
import { checkAndEvaluateMath } from '../checkAndEvaluateMath.js';

/**
* Helper: Transforms typography object to typography shorthand for CSS
Expand All @@ -12,9 +13,11 @@ export function transformTypographyForCSS(
if (typeof value !== 'object') {
return value;
}
const { fontWeight, fontSize, lineHeight, fontFamily } = value;
const { fontFamily } = value;
let { fontWeight, fontSize, lineHeight } = value;
fontWeight = transformFontWeights(fontWeight) as string;
fontSize = transformDimension(checkAndEvaluateMath(fontSize)) as string;
lineHeight = checkAndEvaluateMath(lineHeight) as string;

return `${transformFontWeights(fontWeight)} ${transformDimension(
fontSize,
)}/${lineHeight} ${fontFamily}`;
return `${fontWeight} ${fontSize}/${lineHeight} ${fontFamily}`;
}
3 changes: 1 addition & 2 deletions src/registerTransforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,7 @@ export async function registerTransforms(sd: Core, transformOpts?: TransformOpti
type: 'value',
transitive: true,
matcher: token => typeof token.value === 'string',
// Putting this in strings seems to be required
transformer: token => `${checkAndEvaluateMath(token.value)}`,
transformer: token => checkAndEvaluateMath(token.value),
});

_sd.registerTransform({
Expand Down
61 changes: 61 additions & 0 deletions test/integration/math-in-complex-values.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { expect } from '@esm-bundle/chai';
import StyleDictionary from 'style-dictionary';
import { promises } from 'fs';
import path from 'path';
import { cleanup, init } from './utils.js';

const outputDir = 'test/integration/tokens/';
const outputFileName = 'vars.css';
const outputFilePath = path.resolve(outputDir, outputFileName);

const cfg = {
source: ['test/integration/tokens/math-in-complex-values.tokens.json'],
platforms: {
css: {
transformGroup: 'tokens-studio',
prefix: 'sd',
buildPath: outputDir,
files: [
{
destination: outputFileName,
format: 'css/variables',
},
],
},
},
};

let dict: StyleDictionary.Core | undefined;

describe('sd-transforms advanced tests', () => {
beforeEach(() => {
if (dict) {
cleanup(dict);
}
dict = init(cfg);
});

afterEach(() => {
if (dict) {
cleanup(dict);
}
});

it('supports typography tokens with math or fontweight alias', async () => {
const file = await promises.readFile(outputFilePath, 'utf-8');
expect(file).to.include(`--sdTypo: 400 24px/1.125 Arial Black;`);
});

it('supports border tokens with math width and hexrgba color', async () => {
const file = await promises.readFile(outputFilePath, 'utf-8');
expect(file).to.include(`--sdBorder: 24px dashed rgba(255, 255, 0, 0.5);`);
});

it('supports box shadow tokens with math dimensions, hexrgba color', async () => {
const file = await promises.readFile(outputFilePath, 'utf-8');
expect(file).to.include(`--sdShadowSingle: inset 0 4px 10px 0 rgba(0, 0, 0, 0.4);`);
expect(file).to.include(
`--sdShadowDouble: inset 0 4px 10px 0 rgba(0, 0, 0, 0.4), inset 0 4px 10px 0 rgba(255, 255, 255, 0.2);`,
);
});
});
53 changes: 53 additions & 0 deletions test/integration/tokens/math-in-complex-values.tokens.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"typo": {
"value": {
"fontFamily": "Arial Black",
"fontSize": "16 * 1.5",
"fontWeight": "regular",
"lineHeight": "0.75 * 1.5"
},
"type": "typography"
},
"border": {
"value": {
"color": "rgba(#FFFF00, 0.5)",
"width": "16 * 1.5",
"style": "dashed"
},
"type": "border"
},
"shadow": {
"single": {
"value": {
"x": "0",
"y": "3 + 1",
"blur": "100 / 10",
"spread": "0",
"color": "rgba(#000000,0.4)",
"type": "innerShadow"
},
"type": "boxShadow"
},
"double": {
"value": [
{
"x": "0",
"y": "3 + 1",
"blur": "100 / 10",
"spread": "0",
"color": "rgba(#000000,0.4)",
"type": "innerShadow"
},
{
"x": "0",
"y": "5 - 1",
"blur": "1 * 10",
"spread": "0",
"color": "rgba(#FFFFFF,0.2)",
"type": "innerShadow"
}
],
"type": "boxShadow"
}
}
}

0 comments on commit acd3ddb

Please sign in to comment.