Skip to content

Commit fc9406f

Browse files
Fix styleLint output for all dimension values to be pixel strings instead of arrays
Co-authored-by: lukasoppermann <[email protected]>
1 parent 9ea3162 commit fc9406f

File tree

5 files changed

+140
-1
lines changed

5 files changed

+140
-1
lines changed

src/platforms/styleLint.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const styleLint: PlatformInitializer = (outputFile, prefix, buildPath, op
99
transforms: [
1010
'name/pathToKebabCase',
1111
'color/hex',
12-
'dimension/remPxArray',
12+
'dimension/pixel',
1313
'shadow/css',
1414
'border/css',
1515
'typography/css',

src/primerStyleDictionary.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
colorToRgbaFloat,
77
cubicBezierToCss,
88
dimensionToRem,
9+
dimensionToPixel,
910
dimensionToPixelUnitless,
1011
durationToCss,
1112
figmaAttributes,
@@ -123,6 +124,8 @@ PrimerStyleDictionary.registerTransform(floatToPixelUnitless)
123124

124125
PrimerStyleDictionary.registerTransform(dimensionToRem)
125126

127+
PrimerStyleDictionary.registerTransform(dimensionToPixel)
128+
126129
PrimerStyleDictionary.registerTransform(dimensionToRemPxArray)
127130

128131
PrimerStyleDictionary.registerTransform(dimensionToPixelUnitless)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {dimensionToPixel} from './dimensionToPixel.js'
2+
import {getMockToken} from '../test-utilities/index.js'
3+
4+
describe('Transform: dimensionToPixel', () => {
5+
it('transforms `px` dimension token', () => {
6+
const input = [
7+
getMockToken({
8+
value: {value: 16, unit: 'px'},
9+
}),
10+
]
11+
const expectedOutput = ['16px']
12+
expect(input.map(item => dimensionToPixel.transform(item, {basePxFontSize: 16}, {}))).toStrictEqual(expectedOutput)
13+
})
14+
15+
it('transforms `rem` dimension token', () => {
16+
const input = [
17+
getMockToken({
18+
value: {value: 1, unit: 'rem'},
19+
}),
20+
]
21+
const expectedOutput = ['16px']
22+
expect(input.map(item => dimensionToPixel.transform(item, {basePxFontSize: 16}, {}))).toStrictEqual(expectedOutput)
23+
})
24+
25+
it('transforms `em` dimension token', () => {
26+
const input = [
27+
getMockToken({
28+
value: {value: 1.5, unit: 'em'},
29+
}),
30+
]
31+
const expectedOutput = ['1.5em']
32+
expect(input.map(item => dimensionToPixel.transform(item, {basePxFontSize: 16}, {}))).toStrictEqual(expectedOutput)
33+
})
34+
35+
it('transforms dimension token with `0` value', () => {
36+
const input = [
37+
getMockToken({
38+
value: {value: 0, unit: 'px'},
39+
}),
40+
]
41+
const expectedOutput = ['0']
42+
expect(input.map(item => dimensionToPixel.transform(item, {basePxFontSize: 16}, {}))).toStrictEqual(expectedOutput)
43+
})
44+
45+
it('transforms dimension token with decimal value', () => {
46+
const input = [
47+
getMockToken({
48+
value: {value: 1.5, unit: 'px'},
49+
}),
50+
]
51+
const expectedOutput = ['1.5px']
52+
expect(input.map(item => dimensionToPixel.transform(item, {basePxFontSize: 16}, {}))).toStrictEqual(expectedOutput)
53+
})
54+
55+
it('uses custom base font size', () => {
56+
const input = [
57+
getMockToken({
58+
value: {value: 1, unit: 'rem'},
59+
}),
60+
]
61+
const expectedOutput = ['20px']
62+
expect(input.map(item => dimensionToPixel.transform(item, {basePxFontSize: 20}, {}))).toStrictEqual(expectedOutput)
63+
})
64+
65+
it('throws error for invalid dimension value', () => {
66+
const input = getMockToken({
67+
value: 'invalid',
68+
})
69+
expect(() => dimensionToPixel.transform(input, {basePxFontSize: 16}, {})).toThrow('Invalid dimension token')
70+
})
71+
72+
it('throws error for unsupported unit', () => {
73+
const input = getMockToken({
74+
value: {value: 16, unit: 'vh'},
75+
})
76+
expect(() => dimensionToPixel.transform(input, {basePxFontSize: 16}, {})).toThrow('Invalid dimension token')
77+
})
78+
})

src/transformers/dimensionToPixel.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {isDimension} from '../filters/index.js'
2+
import type {Config, PlatformConfig, Transform, TransformedToken} from 'style-dictionary/types'
3+
4+
/**
5+
* @description base font size from options or 16
6+
* @param options
7+
* @returns number
8+
*/
9+
const getBasePxFontSize = (options?: PlatformConfig): number => (options && options.basePxFontSize) || 16
10+
11+
/**
12+
* @description converts dimension tokens value to `px` string, ignores `em` as they are relative to the font size of the parent element
13+
* @type value transformer — [StyleDictionary.ValueTransform](https://github.com/amzn/style-dictionary/blob/main/types/Transform.d.ts)
14+
* @matcher matches all tokens of $type `dimension`
15+
* @transformer returns a `px` string
16+
*/
17+
export const dimensionToPixel: Transform = {
18+
name: 'dimension/pixel',
19+
type: 'value',
20+
transitive: true,
21+
filter: isDimension,
22+
transform: (token: TransformedToken, config: PlatformConfig, options: Config) => {
23+
const valueProp = options.usesDtcg ? '$value' : 'value'
24+
const baseFont = getBasePxFontSize(config)
25+
const dimensionValue = token[valueProp] as {value: number; unit: string}
26+
27+
if (typeof dimensionValue !== 'object' || !('value' in dimensionValue) || !('unit' in dimensionValue)) {
28+
throw new Error(
29+
`Invalid dimension token: '${token.name}: ${JSON.stringify(token[valueProp])}' must be an object with value and unit properties \n`,
30+
)
31+
}
32+
33+
const {value, unit} = dimensionValue
34+
35+
if (value === 0) {
36+
return '0'
37+
}
38+
39+
if (unit === 'px') {
40+
return `${value}px`
41+
}
42+
43+
if (unit === 'rem') {
44+
// Convert rem to px
45+
return `${value * baseFont}px`
46+
}
47+
48+
if (unit === 'em') {
49+
// Keep em as is since it's relative
50+
return `${value}em`
51+
}
52+
53+
throw new Error(
54+
`Invalid dimension token: '${token.name}: ${JSON.stringify(token[valueProp])}' has unsupported unit '${unit}' \n`,
55+
)
56+
},
57+
}

src/transformers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export {floatToPixelUnitless} from './floatToPixel.js'
88
export {gradientToCss} from './gradientToCss.js'
99
export {dimensionToRem} from './dimensionToRem.js'
1010
export {dimensionToRemPxArray} from './dimensionToRemPxArray.js'
11+
export {dimensionToPixel} from './dimensionToPixel.js'
1112
export {dimensionToPixelUnitless} from './dimensionToPixelUnitless.js'
1213
export {durationToCss} from './durationToCss.js'
1314
export {figmaAttributes} from './figmaAttributes.js'

0 commit comments

Comments
 (0)