From ce69ada01e50eb0e505d3ce4da7933c4969aee6b Mon Sep 17 00:00:00 2001 From: jorenbroekema Date: Wed, 17 May 2023 11:16:46 +0200 Subject: [PATCH] fix: consider empty string props in typo/border/shadow --- .changeset/poor-apples-fetch.md | 5 +++++ src/css/transformBorder.ts | 12 ++++++++---- src/css/transformShadow.ts | 19 +++++++++++-------- src/css/transformTypography.ts | 15 ++++++++------- src/transformDimension.ts | 3 ++- src/utils/is-nothing.ts | 6 ++++++ test/spec/css/transformBorder.spec.ts | 1 + test/spec/css/transformShadow.spec.ts | 2 +- .../css/transformTypographyForCSS.spec.ts | 4 ++-- 9 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 .changeset/poor-apples-fetch.md create mode 100644 src/utils/is-nothing.ts diff --git a/.changeset/poor-apples-fetch.md b/.changeset/poor-apples-fetch.md new file mode 100644 index 0000000..27196e3 --- /dev/null +++ b/.changeset/poor-apples-fetch.md @@ -0,0 +1,5 @@ +--- +'@tokens-studio/sd-transforms': patch +--- + +Consider that properties can also be empty string, which is especially common if the typography/border/shadow tokens are coming from Tokens Studio. diff --git a/src/css/transformBorder.ts b/src/css/transformBorder.ts index a6b1c5a..a72e61b 100644 --- a/src/css/transformBorder.ts +++ b/src/css/transformBorder.ts @@ -1,6 +1,7 @@ import { checkAndEvaluateMath } from '../checkAndEvaluateMath.js'; import { transformDimension } from '../transformDimension.js'; import { transformHEXRGBaForCSS } from './transformHEXRGBa.js'; +import { isNothing } from '../utils/is-nothing.js'; /** * Helper: Transforms border object to border shorthand @@ -8,13 +9,16 @@ import { transformHEXRGBaForCSS } from './transformHEXRGBa.js'; * but if any one of these use a raw value, it will not be transformed. */ export function transformBorderForCSS( - border: Record | undefined | string, + border: Record | undefined | string, ): string | undefined { if (typeof border !== 'object') { return border; } - const { color, width, style } = border; - return `${transformDimension(checkAndEvaluateMath(width)) ?? ''} ${style ?? ''} ${ - transformHEXRGBaForCSS(color) ?? '' + let { color, width } = border; + const { style } = border; + width = transformDimension(checkAndEvaluateMath(width)); + color = transformHEXRGBaForCSS(color); + return `${isNothing(width) ? '' : width} ${isNothing(style) ? '' : style} ${ + isNothing(color) ? '' : color }`.trim(); } diff --git a/src/css/transformShadow.ts b/src/css/transformShadow.ts index fb6c53b..05fd8eb 100644 --- a/src/css/transformShadow.ts +++ b/src/css/transformShadow.ts @@ -1,6 +1,7 @@ import { checkAndEvaluateMath } from '../checkAndEvaluateMath.js'; import { transformDimension } from '../transformDimension.js'; import { transformHEXRGBaForCSS } from './transformHEXRGBa.js'; +import { isNothing } from '../utils/is-nothing.js'; /** * Helper: Transforms boxShadow object to shadow shorthand @@ -8,18 +9,20 @@ import { transformHEXRGBaForCSS } from './transformHEXRGBa.js'; * but if any one of these use a raw value, it will not be transformed. */ export function transformShadowForCSS( - shadow: Record | undefined | string, + shadow: Record | undefined | string, ): string | undefined { if (typeof shadow !== 'object') { return shadow; } let { x, y, blur, spread } = shadow; const { color, type } = shadow; - 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 ?? 0} ${y ?? 0} ${blur ?? 0}${ - spread == null ? ' ' : ` ${spread} ` - }${transformHEXRGBaForCSS(color) ?? 'rgba(0, 0, 0, 1)'}`.trim(); + x = transformDimension(checkAndEvaluateMath(x)); + y = transformDimension(checkAndEvaluateMath(y)); + blur = transformDimension(checkAndEvaluateMath(blur)); + spread = transformDimension(checkAndEvaluateMath(spread)); + return `${type === 'innerShadow' ? 'inset ' : ''}${isNothing(x) ? 0 : x} ${ + isNothing(y) ? 0 : y + } ${isNothing(blur) ? 0 : blur}${isNothing(spread) ? ' ' : ` ${spread} `}${ + transformHEXRGBaForCSS(color) ?? 'rgba(0, 0, 0, 1)' + }`.trim(); } diff --git a/src/css/transformTypography.ts b/src/css/transformTypography.ts index d814266..204939c 100644 --- a/src/css/transformTypography.ts +++ b/src/css/transformTypography.ts @@ -1,6 +1,7 @@ import { transformDimension } from '../transformDimension.js'; import { transformFontWeights } from '../transformFontWeights.js'; import { checkAndEvaluateMath } from '../checkAndEvaluateMath.js'; +import { isNothing } from '../utils/is-nothing.js'; /** * Helper: Transforms typography object to typography shorthand for CSS @@ -8,18 +9,18 @@ import { checkAndEvaluateMath } from '../checkAndEvaluateMath.js'; * If you'd like to output all typography values, you'd rather need to return the typography properties itself */ export function transformTypographyForCSS( - value: Record | undefined | string, + value: Record | undefined | string, ): string | undefined { if (typeof value !== 'object') { return 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; + fontWeight = transformFontWeights(fontWeight); + fontSize = transformDimension(checkAndEvaluateMath(fontSize)); + lineHeight = checkAndEvaluateMath(lineHeight); - return `${fontWeight ?? 400} ${fontSize ?? '16px'}/${lineHeight ?? 1} ${ - fontFamily ?? 'sans-serif' - }`; + return `${isNothing(fontWeight) ? 400 : fontWeight} ${isNothing(fontSize) ? '16px' : fontSize}/${ + isNothing(lineHeight) ? 1 : lineHeight + } ${isNothing(fontFamily) ? 'sans-serif' : fontFamily}`; } diff --git a/src/transformDimension.ts b/src/transformDimension.ts index fee1ff6..130ecf2 100644 --- a/src/transformDimension.ts +++ b/src/transformDimension.ts @@ -7,8 +7,9 @@ export function transformDimension(value: string | undefined | number): string | } // Check if the value is numeric with isNaN, this supports string values as well + // Check if value is not empty string, since this is also not considered "NaN" // Check if the value, when parsed (since it can also be number), does not equal 0 - if (!isNaN(value as number) && parseFloat(value as string) !== 0) { + if (!isNaN(value as number) && value !== '' && parseFloat(value as string) !== 0) { return `${value}px`; } return `${value}`; diff --git a/src/utils/is-nothing.ts b/src/utils/is-nothing.ts new file mode 100644 index 0000000..c0875ae --- /dev/null +++ b/src/utils/is-nothing.ts @@ -0,0 +1,6 @@ +export function isNothing(value: string | null | undefined): boolean { + if (value == null || value === '') { + return true; + } + return false; +} diff --git a/test/spec/css/transformBorder.spec.ts b/test/spec/css/transformBorder.spec.ts index 506d358..ee7ea88 100644 --- a/test/spec/css/transformBorder.spec.ts +++ b/test/spec/css/transformBorder.spec.ts @@ -33,6 +33,7 @@ describe('transform border', () => { expect( transformBorderForCSS({ width: '5', + style: '', }), ).to.equal('5px'); diff --git a/test/spec/css/transformShadow.spec.ts b/test/spec/css/transformShadow.spec.ts index 3ab8f24..f02e180 100644 --- a/test/spec/css/transformShadow.spec.ts +++ b/test/spec/css/transformShadow.spec.ts @@ -49,7 +49,7 @@ describe('transform shadow', () => { it('provides empty string or 0 for missing properties', () => { expect(transformShadowForCSS({})).to.equal('0 0 0 rgba(0, 0, 0, 1)'); - expect(transformShadowForCSS({ x: '5' })).to.equal('5px 0 0 rgba(0, 0, 0, 1)'); + expect(transformShadowForCSS({ x: '5', y: '' })).to.equal('5px 0 0 rgba(0, 0, 0, 1)'); expect(transformShadowForCSS({ spread: '5', color: 'rgba(#000000, 0.5)' })).to.equal( '0 0 0 5px rgba(0, 0, 0, 0.5)', diff --git a/test/spec/css/transformTypographyForCSS.spec.ts b/test/spec/css/transformTypographyForCSS.spec.ts index 6983d2a..eacd149 100644 --- a/test/spec/css/transformTypographyForCSS.spec.ts +++ b/test/spec/css/transformTypographyForCSS.spec.ts @@ -31,10 +31,10 @@ describe('transform typography', () => { expect( transformTypographyForCSS({ fontWeight: 'light', - fontSize: '20', + fontSize: '', fontFamily: 'Arial', }), - ).to.equal('300 20px/1 Arial'); + ).to.equal('300 16px/1 Arial'); expect(transformTypographyForCSS({})).to.equal('400 16px/1 sans-serif'); });