From b3bea1a550032459588a2980e7396c55e28d7b2a Mon Sep 17 00:00:00 2001 From: Lukas Oppermann Date: Thu, 19 Dec 2024 12:09:31 +0100 Subject: [PATCH] add logging utility fn (#1143) * add logging utility fn * reset * fix import --- scripts/buildTokens.ts | 8 ++++ src/transformers/colorToHex.ts | 6 +-- src/transformers/colorToRgbAlpha.ts | 6 +-- src/transformers/shadowToCss.ts | 6 +-- src/transformers/utilities/alpha.ts | 14 ++++-- src/utilities/log.test.ts | 68 +++++++++++++++++++++++++++++ src/utilities/log.ts | 36 +++++++++++++++ 7 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 src/utilities/log.test.ts create mode 100644 src/utilities/log.ts diff --git a/scripts/buildTokens.ts b/scripts/buildTokens.ts index 52087314b..c274fc1ef 100644 --- a/scripts/buildTokens.ts +++ b/scripts/buildTokens.ts @@ -207,6 +207,7 @@ export const buildDesignTokens = async (buildOptions: ConfigGeneratorOptions): P `src/tokens/functional/color/light/*.json5`, `src/tokens/functional/shadow/light.json5`, `src/tokens/functional/border/*.json5`, + `src/tokens/component/*.json5`, ], include: [`src/tokens/base/color/light/light.json5`, 'src/tokens/functional/size/border.json5'], }, @@ -238,6 +239,13 @@ export const buildDesignTokens = async (buildOptions: ConfigGeneratorOptions): P platforms: { deprecated: deprecatedJson(`deprecated/${filename}.json`, buildOptions.prefix, buildOptions.buildPath), }, + log: { + warnings: 'disabled', // 'warn' | 'error' | 'disabled' + verbosity: 'silent', // 'default' | 'silent' | 'verbose' + errors: { + brokenReferences: 'throw', // 'throw' | 'console' + }, + }, }) await extendedSD.buildAllPlatforms() } diff --git a/src/transformers/colorToHex.ts b/src/transformers/colorToHex.ts index d276fcaf9..bd39c5c61 100644 --- a/src/transformers/colorToHex.ts +++ b/src/transformers/colorToHex.ts @@ -1,7 +1,7 @@ import {toHex} from 'color2k' import {isColor} from '../filters/index.js' import {getTokenValue} from './utilities/getTokenValue.js' -import type {Transform, TransformedToken} from 'style-dictionary/types' +import type {PlatformConfig, Transform, TransformedToken} from 'style-dictionary/types' import {alpha} from './utilities/alpha.js' /** * @description converts color tokens value to `hex6` or `hex8` @@ -14,11 +14,11 @@ export const colorToHex: Transform = { type: 'value', transitive: true, filter: isColor, - transform: (token: TransformedToken) => { + transform: (token: TransformedToken, config: PlatformConfig) => { const alphaValue = token.alpha if (alphaValue === null || alphaValue === undefined) { return toHex(getTokenValue(token)) } - return toHex(alpha(getTokenValue(token), alphaValue, token)) + return toHex(alpha(getTokenValue(token), alphaValue, token, config)) }, } diff --git a/src/transformers/colorToRgbAlpha.ts b/src/transformers/colorToRgbAlpha.ts index 409570715..2cd63e796 100644 --- a/src/transformers/colorToRgbAlpha.ts +++ b/src/transformers/colorToRgbAlpha.ts @@ -1,7 +1,7 @@ import {isColorWithAlpha} from '../filters/index.js' import {alpha} from './utilities/alpha.js' import {getTokenValue} from './utilities/getTokenValue.js' -import type {Transform, TransformedToken} from 'style-dictionary/types' +import type {PlatformConfig, Transform, TransformedToken} from 'style-dictionary/types' /** * @description replaces tokens value with `rgba` color using the tokens `alpha` property to specify the value used for alpha * @type value transformer — [StyleDictionary.ValueTransform](https://github.com/amzn/style-dictionary/blob/main/types/Transform.d.ts) @@ -13,8 +13,8 @@ export const colorToRgbAlpha: Transform = { type: 'value', transitive: true, filter: isColorWithAlpha, - transform: (token: TransformedToken) => { + transform: (token: TransformedToken, config: PlatformConfig) => { if (token.alpha === null) return getTokenValue(token) - return alpha(getTokenValue(token), token.alpha, token) + return alpha(getTokenValue(token), token.alpha, token, config) }, } diff --git a/src/transformers/shadowToCss.ts b/src/transformers/shadowToCss.ts index 7ff933ab2..e7ac6a1f0 100644 --- a/src/transformers/shadowToCss.ts +++ b/src/transformers/shadowToCss.ts @@ -4,7 +4,7 @@ import {alpha} from './utilities/alpha.js' import {checkRequiredTokenProperties} from './utilities/checkRequiredTokenProperties.js' import type {ShadowTokenValue} from '../types/shadowTokenValue.js' import {getTokenValue} from './utilities/getTokenValue.js' -import type {Transform, TransformedToken} from 'style-dictionary/types' +import type {PlatformConfig, Transform, TransformedToken} from 'style-dictionary/types' /** * @description converts w3c shadow tokens in css shadow string @@ -17,7 +17,7 @@ export const shadowToCss: Transform = { type: 'value', transitive: true, filter: isShadow, - transform: (token: TransformedToken) => { + transform: (token: TransformedToken, config: PlatformConfig) => { // extract value const value: ShadowTokenValue | ShadowTokenValue[] = getTokenValue(token) const valueProp = token.$value ? '$value' : 'value' @@ -32,7 +32,7 @@ export const shadowToCss: Transform = { /*css box shadow: inset? | offset-x | offset-y | blur-radius | spread-radius | color */ return `${shadow.inset === true ? 'inset ' : ''}${shadow.offsetX} ${shadow.offsetY} ${shadow.blur} ${ shadow.spread - } ${toHex(alpha(getTokenValue({...token, ...{[valueProp]: shadow}}, 'color'), shadow.alpha || 1, token))}` + } ${toHex(alpha(getTokenValue({...token, ...{[valueProp]: shadow}}, 'color'), shadow.alpha || 1, token, config))}` }) .join(', ') }, diff --git a/src/transformers/utilities/alpha.ts b/src/transformers/utilities/alpha.ts index 87b1db06b..3223c0d97 100644 --- a/src/transformers/utilities/alpha.ts +++ b/src/transformers/utilities/alpha.ts @@ -1,5 +1,6 @@ import {rgba, parseToRgba} from 'color2k' -import type {TransformedToken} from 'style-dictionary/types' +import type {PlatformConfig, TransformedToken} from 'style-dictionary/types' +import {log} from '../../utilities/log.js' /** * alpha * @description takes a colors string like hex or rgba and returns an rgba color with the specified alpha value @@ -7,15 +8,20 @@ import type {TransformedToken} from 'style-dictionary/types' * @param desiredAlpha number * @returns rgba value */ -export const alpha = (color: string, desiredAlpha: number, token?: TransformedToken): string => { +export const alpha = ( + color: string, + desiredAlpha: number, + token?: TransformedToken, + config?: PlatformConfig, +): string => { const [r, g, b, a] = parseToRgba(color) if (a < 1 && desiredAlpha < 1) { - // eslint-disable-next-line no-console - console.warn( + log.info( `🚨 You are setting an alpha value of "${desiredAlpha}" for a color with an alpha value (${color}). The previous alpha value will be disregarded as if the color would have been 100% opaque.${ token !== undefined ? `\n ↳ Token: "${token.name}" in file: "${token.filePath}"` : '' }`, + config, ) } diff --git a/src/utilities/log.test.ts b/src/utilities/log.test.ts new file mode 100644 index 000000000..7c0a22c8f --- /dev/null +++ b/src/utilities/log.test.ts @@ -0,0 +1,68 @@ +import type {PlatformConfig} from 'style-dictionary/types' +import {log} from './log.js' + +describe('Utilities: log', () => { + const consoleLogSpy = vi.spyOn(console, 'log') + const consoleWarnSpy = vi.spyOn(console, 'warn') + const consoleErrorSpy = vi.spyOn(console, 'error') + + afterEach(() => { + vi.clearAllMocks() + }) + + it('logs correct type', () => { + log.info('message.log') + log.warning('message.warn') + log.error('message.error') + expect(consoleLogSpy).toHaveBeenLastCalledWith('message.log') + expect(consoleWarnSpy).toHaveBeenLastCalledWith('message.warn') + expect(consoleErrorSpy).toHaveBeenLastCalledWith('message.error') + }) + + it('only logs errors when verbosity silent', () => { + const config = { + log: { + verbosity: 'silent', + }, + } as PlatformConfig + + log.info('message.log', config) + log.warning('message.warn', config) + log.error('message.error', config) + expect(consoleLogSpy).not.toHaveBeenLastCalledWith('message.log') + expect(consoleWarnSpy).not.toHaveBeenLastCalledWith('message.warn') + expect(consoleErrorSpy).toHaveBeenLastCalledWith('message.error') + }) + + it('only logs errors & warnings when verbosity silent', () => { + const config = { + log: { + verbosity: 'default', + warnings: 'warn', + }, + } as PlatformConfig + + log.info('message.log', config) + log.warning('message.warn', config) + log.error('message.error', config) + expect(consoleLogSpy).not.toHaveBeenLastCalledWith('message.log') + expect(consoleWarnSpy).toHaveBeenLastCalledWith('message.warn') + expect(consoleErrorSpy).toHaveBeenLastCalledWith('message.error') + }) + + it('only logs errors & warnings when verbosity silent', () => { + const config = { + log: { + verbosity: 'default', + warnings: 'disabled', + }, + } as PlatformConfig + + log.info('message.log', config) + log.warning('message.warn', config) + log.error('message.error', config) + expect(consoleLogSpy).not.toHaveBeenLastCalledWith('message.log') + expect(consoleWarnSpy).not.toHaveBeenLastCalledWith('message.warn') + expect(consoleErrorSpy).toHaveBeenLastCalledWith('message.error') + }) +}) diff --git a/src/utilities/log.ts b/src/utilities/log.ts new file mode 100644 index 000000000..17e5cf4b8 --- /dev/null +++ b/src/utilities/log.ts @@ -0,0 +1,36 @@ +import type {PlatformConfig} from 'style-dictionary/types' + +const logMessage = (message: string, type: 'info' | 'warning' | 'error' = 'warning', config?: PlatformConfig) => { + // early return if verbosity is silent + if (config?.log?.verbosity === 'silent' && type !== 'error') { + return + } + // early return if verbosity is default and type is info + if (config?.log?.verbosity === 'default' && type === 'info') { + return + } + // early return + if ((config?.log?.warnings === 'disabled' || config?.log?.warnings === 'warn') && type === 'info') { + return + } + // early return + if (config?.log?.warnings === 'disabled' && type === 'warning') { + return + } + if (type === 'warning') { + // eslint-disable-next-line no-console + return console.warn(message) + } + if (type === 'error') { + // eslint-disable-next-line no-console + return console.error(message) + } + // eslint-disable-next-line no-console + console.log(message) +} + +export const log = { + info: (message: string, config?: PlatformConfig) => logMessage(message, 'info', config), + warning: (message: string, config?: PlatformConfig) => logMessage(message, 'warning', config), + error: (message: string, config?: PlatformConfig) => logMessage(message, 'error', config), +}