@tokens-studio/sd-transforms
Advanced tools
Comparing version 0.16.1 to 1.0.0
@@ -1,1 +0,2 @@ | ||
export declare function checkAndEvaluateMath(expr: string | number | boolean | undefined): string | number | boolean | undefined; | ||
import { DesignToken } from 'style-dictionary/types'; | ||
export declare function checkAndEvaluateMath(token: DesignToken): DesignToken['value']; |
import { Parser } from 'expr-eval-fork'; | ||
import { parse as parse_1, reduceExpression } from '../bundled_CJS_deps/postcss-calc-ast-parser/dist/index.js'; | ||
import { parse, reduceExpression } from '@bundled-es-modules/postcss-calc-ast-parser'; | ||
const mathChars = ['+', '-', '*', '/']; | ||
@@ -92,3 +91,5 @@ const parser = new Parser(); | ||
while ((matchArr = unitRegex.exec(noPixExpr)) !== null) { | ||
foundUnits.add(matchArr.groups.unit); | ||
if (matchArr?.groups) { | ||
foundUnits.add(matchArr.groups.unit); | ||
} | ||
} | ||
@@ -101,3 +102,3 @@ // multiple units (besides px) found, cannot parse the expression | ||
// Remove it here so we can evaluate expressions like 16px + 24px | ||
const calcParsed = parse_1(noPixExpr, { allowInlineCommnets: false }); | ||
const calcParsed = parse(noPixExpr, { allowInlineCommnets: false }); | ||
// No expression to evaluate, just return it (in case of number as string e.g. '10') | ||
@@ -121,14 +122,57 @@ if (calcParsed.nodes.length === 1 && calcParsed.nodes[0].type === 'Number') { | ||
} | ||
function checkAndEvaluateMath(expr) { | ||
if (typeof expr !== 'string') { | ||
export function checkAndEvaluateMath(token) { | ||
const expr = token.$value ?? token.value; | ||
const type = token.$type ?? token.type; | ||
if (!['string', 'object'].includes(typeof expr)) { | ||
return expr; | ||
} | ||
const exprs = splitMultiIntoSingleValues(expr); | ||
const reducedExprs = exprs.map(_expr => parseAndReduce(_expr)); | ||
if (reducedExprs.length === 1) { | ||
return reducedExprs[0]; | ||
const resolveMath = (expr) => { | ||
if (typeof expr !== 'string') { | ||
return expr; | ||
} | ||
const exprs = splitMultiIntoSingleValues(expr); | ||
const reducedExprs = exprs.map(_expr => parseAndReduce(_expr)); | ||
if (reducedExprs.length === 1) { | ||
return reducedExprs[0]; | ||
} | ||
return reducedExprs.join(' '); | ||
}; | ||
const transformProp = (val, prop) => { | ||
val[prop] = resolveMath(val[prop]); | ||
return val; | ||
}; | ||
let transformed = expr; | ||
switch (type) { | ||
case 'typography': | ||
case 'border': { | ||
transformed = transformed; | ||
// double check that expr is still an object and not already shorthand transformed to a string | ||
if (typeof expr === 'object') { | ||
Object.keys(transformed).forEach(prop => { | ||
transformed = transformProp(transformed, prop); | ||
}); | ||
} | ||
break; | ||
} | ||
case 'shadow': { | ||
transformed = transformed; | ||
const transformShadow = (shadowVal) => { | ||
// double check that expr is still an object and not already shorthand transformed to a string | ||
if (typeof expr === 'object') { | ||
Object.keys(shadowVal).forEach(prop => { | ||
shadowVal = transformProp(shadowVal, prop); | ||
}); | ||
} | ||
return shadowVal; | ||
}; | ||
if (Array.isArray(transformed)) { | ||
transformed = transformed.map(transformShadow); | ||
} | ||
transformed = transformShadow(transformed); | ||
break; | ||
} | ||
default: | ||
transformed = resolveMath(transformed); | ||
} | ||
return reducedExprs.join(' '); | ||
return transformed; | ||
} | ||
export { checkAndEvaluateMath }; |
@@ -1,2 +0,2 @@ | ||
function darken(color, colorSpace, amount) { | ||
export function darken(color, colorSpace, amount) { | ||
switch (colorSpace) { | ||
@@ -43,3 +43,1 @@ case 'lch': { | ||
} | ||
export { darken }; |
@@ -1,2 +0,2 @@ | ||
function lighten(color, colorSpace, amount) { | ||
export function lighten(color, colorSpace, amount) { | ||
switch (colorSpace) { | ||
@@ -43,3 +43,1 @@ case 'lch': { | ||
} | ||
export { lighten }; |
import Color from 'colorjs.io'; | ||
function mix(color, colorSpace, amount, mixColor) { | ||
export function mix(color, colorSpace, amount, mixColor) { | ||
const mixValue = Math.max(0, Math.min(1, Number(amount))); | ||
return new Color(color.mix(mixColor, mixValue, { space: colorSpace }).toString()); | ||
} | ||
export { mix }; |
@@ -6,3 +6,2 @@ import Color from 'colorjs.io'; | ||
import { lighten } from './lighten.js'; | ||
// Users using UIColor swift format are blocked from using such transform in | ||
@@ -25,3 +24,3 @@ // combination with this color modify transform when using references. | ||
} | ||
function modifyColor(baseColor, modifier) { | ||
export function modifyColor(baseColor, modifier) { | ||
if (baseColor === undefined) { | ||
@@ -72,3 +71,1 @@ return baseColor; | ||
} | ||
export { modifyColor }; |
@@ -1,11 +0,7 @@ | ||
import usesReferences from '../../bundled_CJS_deps/style-dictionary/lib/utils/references/usesReferences.js'; | ||
import '../../bundled_CJS_deps/style-dictionary/lib/utils/references/getReferences.js'; | ||
import '../../bundled_CJS_deps/style-dictionary/lib/utils/references/resolveReferences.js'; | ||
import '../../bundled_CJS_deps/style-dictionary/lib/utils/references/outputReferencesFilter.js'; | ||
import { usesReferences } from 'style-dictionary/utils'; | ||
import { modifyColor } from './modifyColor.js'; | ||
/** | ||
* Helper: Transforms color tokens with tokens studio color modifiers | ||
*/ | ||
function transformColorModifiers(token, options) { | ||
export function transformColorModifiers(token, options) { | ||
const modifier = token.$extensions['studio.tokens']?.modify; | ||
@@ -23,3 +19,1 @@ // If some of the modifier props contain references or the modifier itself is a reference | ||
} | ||
export { transformColorModifiers }; |
@@ -1,2 +0,2 @@ | ||
function transparentize(color, amount) { | ||
export function transparentize(color, amount) { | ||
const _color = color; | ||
@@ -6,3 +6,1 @@ _color.alpha = Math.max(0, Math.min(1, Number(amount))); | ||
} | ||
export { transparentize }; |
@@ -0,4 +1,5 @@ | ||
import { DesignToken } from 'style-dictionary/types'; | ||
/** | ||
* Helper: Transforms typography object to typography shorthand for Jetpack Compose | ||
*/ | ||
export declare function transformTypographyForCompose(value: Record<string, string> | undefined): string | undefined; | ||
export declare function transformTypographyForCompose(token: DesignToken): DesignToken['value']; |
@@ -1,10 +0,9 @@ | ||
import { transformFontWeights } from '../transformFontWeights.js'; | ||
import { transformFontWeight } from '../transformFontWeight.js'; | ||
/** | ||
* Helper: Transforms typography object to typography shorthand for Jetpack Compose | ||
*/ | ||
function transformTypographyForCompose(value) { | ||
if (value === undefined) { | ||
return value; | ||
} | ||
export function transformTypographyForCompose(token) { | ||
const val = token.$value ?? token.value; | ||
if (val === undefined) | ||
return undefined; | ||
/** | ||
@@ -30,7 +29,9 @@ * Mapping between https://docs.tokens.studio/available-tokens/typography-tokens | ||
*/ | ||
return `${Object.entries(value).reduce((acc, [propName, val]) => `${acc}${textStylePropertiesMapping[propName] | ||
? `${propName === 'fontWeight' ? transformFontWeights(val) : val}\n` | ||
return `${Object.entries(val).reduce((acc, [propName, v]) => `${acc}${textStylePropertiesMapping[propName] | ||
? `${propName === 'fontWeight' | ||
? transformFontWeight({ | ||
value: v, | ||
}) | ||
: v}\n` | ||
: ''}`, 'TextStyle(\n')})`; | ||
} | ||
export { transformTypographyForCompose }; |
@@ -0,1 +1,2 @@ | ||
import { DesignToken } from 'style-dictionary/types'; | ||
/** | ||
@@ -6,2 +7,2 @@ * Helper: Transforms hex rgba colors used in figma tokens: | ||
*/ | ||
export declare function transformHEXRGBaForCSS(value: string | undefined): string | undefined; | ||
export declare function transformHEXRGBaForCSS(token: DesignToken): DesignToken['value']; |
@@ -1,3 +0,2 @@ | ||
import { parseToRgba } from 'color2k'; | ||
import Color from 'colorjs.io'; | ||
/** | ||
@@ -8,19 +7,43 @@ * Helper: Transforms hex rgba colors used in figma tokens: | ||
*/ | ||
function transformHEXRGBaForCSS(value) { | ||
if (value === undefined) { | ||
return value; | ||
} | ||
const regex = /rgba\(\s*(?<hex>#.+?)\s*,\s*(?<alpha>\d*(\.\d*|%)*)\s*\)/g; | ||
return value.replace(regex, (match, hex, alpha) => { | ||
try { | ||
const [r, g, b] = parseToRgba(hex); | ||
return `rgba(${r}, ${g}, ${b}, ${alpha})`; | ||
export function transformHEXRGBaForCSS(token) { | ||
const val = token.$value ?? token.value; | ||
const type = token.$type ?? token.type; | ||
if (val === undefined) | ||
return undefined; | ||
const transformHEXRGBa = (val) => { | ||
const regex = /rgba\(\s*(?<hex>#.+?)\s*,\s*(?<alpha>\d*(\.\d*|%)*)\s*\)/g; | ||
return val.replace(regex, (match, hex, alpha) => { | ||
try { | ||
const [r, g, b] = new Color(hex).srgb; | ||
return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${alpha})`; | ||
} | ||
catch (e) { | ||
console.warn(`Tried parsing "${hex}" as a hex value, but failed.`); | ||
return match; | ||
} | ||
}); | ||
}; | ||
const transformProp = (val, prop) => { | ||
if (val[prop] !== undefined) { | ||
val[prop] = transformHEXRGBa(val[prop]); | ||
} | ||
catch (e) { | ||
console.warn(`Tried parsing "${hex}" as a hex value, but failed.`); | ||
return match; | ||
return val; | ||
}; | ||
let transformed = val; | ||
switch (type) { | ||
case 'border': | ||
case 'shadow': { | ||
transformed = transformed; | ||
if (Array.isArray(transformed)) { | ||
transformed = transformed.map(item => transformProp(item, 'color')); | ||
} | ||
else { | ||
transformed = transformProp(transformed, 'color'); | ||
} | ||
break; | ||
} | ||
}); | ||
default: | ||
transformed = transformHEXRGBa(val); | ||
} | ||
return transformed; | ||
} | ||
export { transformHEXRGBaForCSS }; |
@@ -0,4 +1,5 @@ | ||
import { DesignToken } from 'style-dictionary/types'; | ||
/** | ||
* Helper: Transforms letter spacing % to em | ||
*/ | ||
export declare function transformLetterSpacingForCSS(value: string | number | undefined): string | undefined; | ||
export declare function transformLetterSpacingForCSS(token: DesignToken): DesignToken['value']; |
import { percentageToDecimal } from '../utils/percentageToDecimal.js'; | ||
/** | ||
* Helper: Transforms letter spacing % to em | ||
*/ | ||
function transformLetterSpacingForCSS(value) { | ||
if (value === undefined) { | ||
return value; | ||
export function transformLetterSpacingForCSS(token) { | ||
const val = token.$value ?? token.value; | ||
const type = token.$type ?? token.type; | ||
if (val === undefined) | ||
return undefined; | ||
const transformLetterSpacing = (letterspacing) => { | ||
const decimal = percentageToDecimal(letterspacing); | ||
return typeof decimal === 'string' || isNaN(decimal) ? `${letterspacing}` : `${decimal}em`; | ||
}; | ||
if (type === 'typography') { | ||
if (val.letterSpacing !== undefined) { | ||
return { | ||
...val, | ||
letterSpacing: transformLetterSpacing(val.letterSpacing), | ||
}; | ||
} | ||
return val; | ||
} | ||
const decimal = percentageToDecimal(value); | ||
return typeof decimal === 'string' || isNaN(decimal) ? `${value}` : `${decimal}em`; | ||
return transformLetterSpacing(val); | ||
} | ||
export { transformLetterSpacingForCSS }; |
@@ -1,6 +0,10 @@ | ||
/** | ||
* Helper: Transforms boxShadow object to shadow shorthand | ||
* This currently works fine if every value uses an alias, | ||
* but if any one of these use a raw value, it will not be transformed. | ||
*/ | ||
export declare function transformShadowForCSS(shadow: Record<string, string | undefined> | undefined | string): string | undefined; | ||
import { SingleBoxShadowToken } from '@tokens-studio/types'; | ||
export declare function transformShadow(value: SingleBoxShadowToken['value']): string | import("@tokens-studio/types").TokenBoxshadowValue | { | ||
type: string | undefined; | ||
color: string; | ||
x: string | number; | ||
y: string | number; | ||
blur: string | number; | ||
spread: string | number; | ||
blendMode?: string; | ||
}[] | undefined; |
@@ -1,24 +0,15 @@ | ||
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 | ||
* This currently works fine if every value uses an alias, | ||
* but if any one of these use a raw value, it will not be transformed. | ||
*/ | ||
function transformShadowForCSS(shadow) { | ||
if (typeof shadow !== 'object') { | ||
return shadow; | ||
export function transformShadow(value) { | ||
const alignShadowType = (val) => { | ||
return val === 'innerShadow' || val === 'inset' ? 'inset' : undefined; | ||
}; | ||
if (Array.isArray(value)) { | ||
return value.map(v => ({ | ||
...v, | ||
type: alignShadowType(v.type), | ||
})); | ||
} | ||
let { x, y, blur, spread } = shadow; | ||
const { color, type } = shadow; | ||
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(); | ||
if (typeof value === 'object') { | ||
value.type = alignShadowType(value.type); | ||
} | ||
return value; | ||
} | ||
export { transformShadowForCSS }; |
@@ -1,19 +0,39 @@ | ||
export { registerTransforms } from './registerTransforms.js'; | ||
export { transforms } from './registerTransforms.js'; | ||
export { expandComposites } from './parsers/expand-composites.js'; | ||
export { excludeParentKeys } from './parsers/exclude-parent-keys.js'; | ||
export { addFontStyles } from './parsers/add-font-styles.js'; | ||
export { parseTokens } from './parsers/parse-tokens.js'; | ||
export { register, getTransforms } from './register.js'; | ||
export { addFontStyles } from './preprocessors/add-font-styles.js'; | ||
export { alignTypes } from './preprocessors/align-types.js'; | ||
export { excludeParentKeys } from './preprocessors/exclude-parent-keys.js'; | ||
export { parseTokens } from './preprocessors/parse-tokens.js'; | ||
export { mapDescriptionToComment } from './mapDescriptionToComment.js'; | ||
export { checkAndEvaluateMath } from './checkAndEvaluateMath.js'; | ||
export { transformDimension } from './transformDimension.js'; | ||
export { transformFontWeights } from './transformFontWeights.js'; | ||
export { transformFontWeight } from './transformFontWeight.js'; | ||
export { transformColorModifiers } from './color-modifiers/transformColorModifiers.js'; | ||
export { transformLineHeight } from './transformLineHeight.js'; | ||
export { transformShadowForCSS } from './css/transformShadow.js'; | ||
export { transformBorderForCSS } from './css/transformBorder.js'; | ||
export { transformTypographyForCSS } from './css/transformTypography.js'; | ||
export { transformOpacity } from './transformOpacity.js'; | ||
export { transformHEXRGBaForCSS } from './css/transformHEXRGBa.js'; | ||
export { transformLetterSpacingForCSS } from './css/transformLetterSpacing.js'; | ||
export { transformShadow } from './css/transformShadow.js'; | ||
export { transformTypographyForCompose } from './compose/transformTypography.js'; | ||
export { permutateThemes } from './permutateThemes.js'; | ||
/** | ||
* Some of the Tokens Studio typography/shadow props need to be aligned | ||
* when expanding them through StyleDictionary expand | ||
*/ | ||
export declare const expandTypesMap: { | ||
typography: { | ||
paragraphSpacing: string; | ||
paragraphIndent: string; | ||
textDecoration: string; | ||
textCase: string; | ||
}; | ||
/** | ||
* boxShadow/x/y are not shadow/offsetX/offsetY here because the SD expand on global level | ||
* happens before these types are aligned in sd-transforms preprocessor | ||
*/ | ||
boxShadow: { | ||
x: string; | ||
y: string; | ||
blur: string; | ||
spread: string; | ||
}; | ||
}; |
@@ -1,18 +0,39 @@ | ||
export { registerTransforms, transforms } from './registerTransforms.js'; | ||
export { expandComposites } from './parsers/expand-composites.js'; | ||
export { excludeParentKeys } from './parsers/exclude-parent-keys.js'; | ||
export { addFontStyles } from './parsers/add-font-styles.js'; | ||
export { parseTokens } from './parsers/parse-tokens.js'; | ||
export { register, getTransforms } from './register.js'; | ||
export { addFontStyles } from './preprocessors/add-font-styles.js'; | ||
export { alignTypes } from './preprocessors/align-types.js'; | ||
export { excludeParentKeys } from './preprocessors/exclude-parent-keys.js'; | ||
export { parseTokens } from './preprocessors/parse-tokens.js'; | ||
export { mapDescriptionToComment } from './mapDescriptionToComment.js'; | ||
export { checkAndEvaluateMath } from './checkAndEvaluateMath.js'; | ||
export { transformDimension } from './transformDimension.js'; | ||
export { transformFontWeights } from './transformFontWeights.js'; | ||
export { transformFontWeight } from './transformFontWeight.js'; | ||
export { transformColorModifiers } from './color-modifiers/transformColorModifiers.js'; | ||
export { transformLineHeight } from './transformLineHeight.js'; | ||
export { transformShadowForCSS } from './css/transformShadow.js'; | ||
export { transformBorderForCSS } from './css/transformBorder.js'; | ||
export { transformTypographyForCSS } from './css/transformTypography.js'; | ||
export { transformOpacity } from './transformOpacity.js'; | ||
export { transformHEXRGBaForCSS } from './css/transformHEXRGBa.js'; | ||
export { transformLetterSpacingForCSS } from './css/transformLetterSpacing.js'; | ||
export { transformShadow } from './css/transformShadow.js'; | ||
export { transformTypographyForCompose } from './compose/transformTypography.js'; | ||
export { permutateThemes } from './permutateThemes.js'; | ||
/** | ||
* Some of the Tokens Studio typography/shadow props need to be aligned | ||
* when expanding them through StyleDictionary expand | ||
*/ | ||
export const expandTypesMap = { | ||
typography: { | ||
paragraphSpacing: 'dimension', | ||
paragraphIndent: 'dimension', | ||
textDecoration: 'other', | ||
textCase: 'other', | ||
}, | ||
/** | ||
* boxShadow/x/y are not shadow/offsetX/offsetY here because the SD expand on global level | ||
* happens before these types are aligned in sd-transforms preprocessor | ||
*/ | ||
boxShadow: { | ||
x: 'dimension', | ||
y: 'dimension', | ||
blur: 'dimension', | ||
spread: 'dimension', | ||
}, | ||
}; |
@@ -5,9 +5,8 @@ /** | ||
*/ | ||
function mapDescriptionToComment(token) { | ||
export function mapDescriptionToComment(token) { | ||
// intentional mutation of the original object | ||
const _t = token; | ||
_t.comment = _t.description.replace(/\r?\n|\r/g, ' '); // Strip out newline and carriage returns, replacing them with space | ||
// Replace carriage returns with just newlines | ||
_t.comment = _t.description.replace(/\r?\n|\r/g, '\n'); | ||
return _t; | ||
} | ||
export { mapDescriptionToComment }; |
function mapThemesToSetsObject(themes) { | ||
return Object.fromEntries(themes.map(theme => [theme.name, filterTokenSets(theme.selectedTokenSets)])); | ||
} | ||
function permutateThemes(themes, { separator = '-' } = {}) { | ||
export function permutateThemes(themes, { separator = '-' } = {}) { | ||
if (themes.some(theme => theme.group)) { | ||
@@ -55,3 +55,1 @@ // Sort themes by groups | ||
} | ||
export { permutateThemes }; |
@@ -0,4 +1,5 @@ | ||
import { DesignToken } from 'style-dictionary/types'; | ||
/** | ||
* Helper: Transforms dimensions to px | ||
*/ | ||
export declare function transformDimension(value: string | undefined | number): string | undefined; | ||
export declare function transformDimension(token: DesignToken): DesignToken['value']; |
@@ -1,17 +0,57 @@ | ||
/** | ||
* Helper: Transforms dimensions to px | ||
*/ | ||
function transformDimension(value) { | ||
if (value === undefined) { | ||
return value; | ||
} | ||
function _transformDimension(dim) { | ||
// 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) && value !== '' && parseFloat(value) !== 0) { | ||
return `${value}px`; | ||
if (!isNaN(dim) && dim !== '' && parseFloat(dim) !== 0) { | ||
return `${dim}px`; | ||
} | ||
return `${value}`; | ||
return `${dim}`; | ||
} | ||
export { transformDimension }; | ||
/** | ||
* Helper: Transforms dimensions to px | ||
*/ | ||
export function transformDimension(token) { | ||
const val = (token.$value ?? token.value); | ||
const type = token.$type ?? token.type; | ||
if (val === undefined) | ||
return undefined; | ||
const transformProp = (val, prop) => { | ||
if (val[prop] !== undefined) { | ||
val[prop] = _transformDimension(val[prop]); | ||
} | ||
return val; | ||
}; | ||
let transformed = val; | ||
switch (type) { | ||
case 'typography': { | ||
transformed = transformed; | ||
transformed = transformProp(transformed, 'fontSize'); | ||
break; | ||
} | ||
case 'shadow': { | ||
transformed = transformed; | ||
const transformShadow = (shadowVal) => { | ||
['offsetX', 'offsetY', 'blur', 'spread'].forEach(prop => { | ||
shadowVal = transformProp(shadowVal, prop); | ||
}); | ||
return shadowVal; | ||
}; | ||
if (Array.isArray(transformed)) { | ||
transformed = transformed.map(transformShadow); | ||
} | ||
else { | ||
transformed = transformShadow(transformed); | ||
} | ||
break; | ||
} | ||
case 'border': { | ||
transformed = transformed; | ||
transformed = transformProp(transformed, 'width'); | ||
break; | ||
} | ||
default: | ||
transformed = transformed; | ||
transformed = _transformDimension(transformed); | ||
} | ||
return transformed; | ||
} |
@@ -0,1 +1,2 @@ | ||
import { DesignToken } from 'style-dictionary/types'; | ||
/** | ||
@@ -6,2 +7,2 @@ * Helper: Transforms line-height % to unit-less decimal value | ||
*/ | ||
export declare function transformLineHeight(value: string | number | undefined): string | number | undefined; | ||
export declare function transformLineHeight(token: DesignToken): DesignToken['value']; |
import { percentageToDecimal } from './utils/percentageToDecimal.js'; | ||
/** | ||
@@ -8,10 +7,21 @@ * Helper: Transforms line-height % to unit-less decimal value | ||
*/ | ||
function transformLineHeight(value) { | ||
if (value === undefined) { | ||
return value; | ||
export function transformLineHeight(token) { | ||
const val = token.$value ?? token.value; | ||
const type = token.$type ?? token.type; | ||
if (val === undefined) | ||
return undefined; | ||
const transformLH = (lineHeight) => { | ||
const decimal = percentageToDecimal(lineHeight); | ||
return typeof decimal === 'string' || isNaN(decimal) ? `${lineHeight}` : decimal; | ||
}; | ||
if (type === 'typography') { | ||
if (val.lineHeight !== undefined) { | ||
return { | ||
...val, | ||
lineHeight: transformLH(val.lineHeight), | ||
}; | ||
} | ||
return val; | ||
} | ||
const decimal = percentageToDecimal(value); | ||
return typeof decimal === 'string' || isNaN(decimal) ? `${value}` : decimal; | ||
return transformLH(val); | ||
} | ||
export { transformLineHeight }; |
import { percentageToDecimal } from './utils/percentageToDecimal.js'; | ||
/** | ||
@@ -8,3 +7,3 @@ * Helper: Transforms opacity % to a decimal point number | ||
*/ | ||
function transformOpacity(value) { | ||
export function transformOpacity(value) { | ||
if (value === undefined) { | ||
@@ -16,3 +15,1 @@ return value; | ||
} | ||
export { transformOpacity }; |
@@ -1,12 +0,1 @@ | ||
import { SingleBorderToken, SingleBoxShadowToken, SingleCompositionToken, SingleToken, SingleTypographyToken } from '@tokens-studio/types'; | ||
export type Expandables = SingleCompositionToken | SingleTypographyToken | SingleBorderToken | SingleBoxShadowToken; | ||
export declare const expandablesAsStringsArr: string[]; | ||
export type ExpandablesAsStrings = (typeof expandablesAsStringsArr)[number]; | ||
export type ExpandFilter<T extends SingleToken> = (token: T, filePath?: string) => boolean; | ||
export interface ExpandOptions { | ||
typography?: boolean | ExpandFilter<SingleTypographyToken>; | ||
border?: boolean | ExpandFilter<SingleBorderToken>; | ||
shadow?: boolean | ExpandFilter<SingleBoxShadowToken>; | ||
composition?: boolean | ExpandFilter<SingleCompositionToken>; | ||
} | ||
export type ColorModifierFormat = 'hex' | 'hsl' | 'lch' | 'p3' | 'srgb'; | ||
@@ -17,6 +6,8 @@ export interface ColorModifierOptions { | ||
export interface TransformOptions { | ||
platform?: 'css' | 'compose'; | ||
name?: string; | ||
withSDBuiltins?: boolean; | ||
alwaysAddFontStyle?: boolean; | ||
expand?: ExpandOptions | false; | ||
excludeParentKeys?: boolean; | ||
['ts/color/modifiers']?: ColorModifierOptions; | ||
} |
@@ -1,3 +0,1 @@ | ||
const expandablesAsStringsArr = ['composition', 'typography', 'border', 'boxShadow']; | ||
export { expandablesAsStringsArr }; | ||
export {}; |
@@ -1,2 +0,2 @@ | ||
function isNothing(value) { | ||
export function isNothing(value) { | ||
if (value == null || value === '') { | ||
@@ -7,3 +7,1 @@ return true; | ||
} | ||
export { isNothing }; |
@@ -1,2 +0,2 @@ | ||
function percentageToDecimal(value) { | ||
export function percentageToDecimal(value) { | ||
if (!`${value}`.endsWith('%')) { | ||
@@ -9,3 +9,1 @@ return `${value}`; | ||
} | ||
export { percentageToDecimal }; |
{ | ||
"name": "@tokens-studio/sd-transforms", | ||
"version": "0.16.1", | ||
"version": "1.0.0", | ||
"description": "Custom transforms for Style-Dictionary, to work with Design Tokens that are exported from Tokens Studio", | ||
@@ -13,9 +13,4 @@ "license": "MIT", | ||
"exports": { | ||
".": { | ||
"require": "./dist/src/index.cjs", | ||
"import": "./dist/src/index.js" | ||
} | ||
".": "./dist/index.js" | ||
}, | ||
"main": "./dist/src/index.cjs", | ||
"module": "./dist/src/index.js", | ||
"files": [ | ||
@@ -25,3 +20,3 @@ "dist" | ||
"scripts": { | ||
"build": "rimraf dist && rollup -c rollup.config.mjs && node ./handle-bundled-cjs-deps.js", | ||
"build": "tsc", | ||
"format": "npm run format:eslint && npm run format:prettier", | ||
@@ -42,20 +37,17 @@ "format:eslint": "eslint --ext .ts,.html . --fix", | ||
}, | ||
"types": "./dist/src/index.d.ts", | ||
"dependencies": { | ||
"@bundled-es-modules/deepmerge": "^4.3.1", | ||
"@bundled-es-modules/postcss-calc-ast-parser": "^0.1.6", | ||
"@tokens-studio/types": "^0.4.0", | ||
"color2k": "^2.0.1", | ||
"colorjs.io": "^0.4.3", | ||
"deepmerge": "^4.3.1", | ||
"expr-eval-fork": "^2.0.2", | ||
"is-mergeable-object": "^1.1.1", | ||
"postcss-calc-ast-parser": "^0.1.4" | ||
"is-mergeable-object": "^1.1.1" | ||
}, | ||
"peerDependencies": { | ||
"style-dictionary": "^4.0.0-prerelease.27" | ||
"style-dictionary": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"@changesets/cli": "^2.26.0", | ||
"@esm-bundle/chai": "^4.3.4-fix.0", | ||
"@rollup/plugin-commonjs": "^24.1.0", | ||
"@rollup/plugin-typescript": "^11.0.0", | ||
"@changesets/cli": "^2.27.6", | ||
"@types/chai": "^4.3.16", | ||
"@types/mocha": "^10.0.7", | ||
"@types/tinycolor2": "^1.4.6", | ||
@@ -65,10 +57,8 @@ "@typescript-eslint/eslint-plugin": "^5.54.0", | ||
"@web/dev-server-esbuild": "^0.3.3", | ||
"@web/dev-server-rollup": "^0.5.0", | ||
"@web/test-runner": "^0.15.1", | ||
"@web/test-runner-playwright": "^0.9.0", | ||
"@web/test-runner": "^0.18.2", | ||
"@web/test-runner-playwright": "^0.11.0", | ||
"chai": "^5.1.1", | ||
"eslint": "^8.32.0", | ||
"eslint-config-prettier": "^8.6.0", | ||
"eslint-plugin-import": "^2.27.5", | ||
"eslint-plugin-mocha": "^10.2.0", | ||
"glob": "^10.2.6", | ||
"eslint-plugin-mocha": "^10.4.3", | ||
"hanbi": "^1.0.3", | ||
@@ -78,10 +68,8 @@ "husky": "^8.0.0", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^2.8.3", | ||
"prettier": "^3.3.2", | ||
"prettier-package-json": "^2.8.0", | ||
"rimraf": "^4.1.3", | ||
"rollup": "^3.18.0", | ||
"tinycolor2": "^1.6.0", | ||
"ts-mocha": "^10.0.0", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^5.3.3" | ||
"typescript": "^5.5.2" | ||
}, | ||
@@ -94,3 +82,3 @@ "keywords": [ | ||
"engines": { | ||
"node": ">=17.0.0" | ||
"node": ">=18.0.0" | ||
}, | ||
@@ -97,0 +85,0 @@ "prettier": { |
284
README.md
@@ -5,2 +5,4 @@ # Style Dictionary Transforms for Tokens Studio | ||
> Note: this README contains examples that assume latest version of this package & v4 style-dictionary latest prerelease. | ||
## Table of contents | ||
@@ -20,4 +22,2 @@ | ||
> This library is currently in beta. | ||
This package contains custom transforms for [Style-Dictionary](https://amzn.github.io/style-dictionary/#/), | ||
@@ -28,4 +28,3 @@ to work with Design Tokens that are exported from [Tokens Studio](https://tokens.studio/): | ||
- Expands composition tokens into multiple, optionally also does so for typography, border and shadow tokens -> parser | ||
- Optionally excludes parent keys from your tokens file, e.g. when using single-file export from Tokens Studio Figma plugin -> parser | ||
- Optionally excludes parent keys from your tokens file, e.g. when using single-file export from Tokens Studio Figma plugin -> preprocessor | ||
- Maps token descriptions to comments -> `ts/descriptionToComment` | ||
@@ -43,6 +42,3 @@ - Check and evaluate Math expressions (transitive) -> `ts/resolveMath` | ||
- Transform colors to `rgba()` format -> `ts/color/css/hexrgba` | ||
- Transform font family into valid CSS, adding single quotes if necessary -> `ts/typography/css/fontFamily` | ||
- Transform typography objects to CSS shorthand -> `ts/typography/css/shorthand` | ||
- Transform Tokens Studio shadow objects to CSS shadow shorthand -> `ts/shadow/css/shorthand` | ||
- Transform border objects to CSS border shorthand -> `ts/border/css/shorthand` | ||
- Transform shadow "type" property "innerShadow" to "inset" -> `ts/shadow/innerShadow` | ||
@@ -75,14 +71,13 @@ Android: | ||
| >= **4.0.0**-prerelease.**27** | >= **0.16.0** | | ||
| >= **4.0.0** | >= **1.0.0** | | ||
This may seem a little tedious, but the reason is because `sd-transforms` is still in alpha, and Style Dictionary v4 is still being worked on, iteratively doing lots of breaking changes. | ||
Now that Style Dictionary v4 is released, and `sd-transforms` v1 is released and out of alpha state,both APIs are stable and the recommendation is to use these. | ||
This will be much simpler when Style Dictionary v4 is released, at that point `sd-transforms` v1 will be released and be out of alpha. | ||
Both APIs will be stable then. | ||
## Usage | ||
> Note: this library is available both in CJS and ESM | ||
> [!NOTE] | ||
> This library is only available in ESM | ||
```js | ||
import { registerTransforms } from '@tokens-studio/sd-transforms'; | ||
import { register } from '@tokens-studio/sd-transforms'; | ||
import StyleDictionary from 'style-dictionary'; | ||
@@ -92,6 +87,8 @@ | ||
// that is installed as a dependency of this package. | ||
registerTransforms(StyleDictionary); | ||
register(StyleDictionary); | ||
const sd = StyleDictionary.extend({ | ||
source: ['**/*.json'], // <-- make sure to have this match your token files!!! | ||
const sd = new StyleDictionary({ | ||
// make sure to have source match your token files! | ||
// be careful about accidentally matching your package.json or similar files that are not tokens | ||
source: ['tokens/**/*.json'], | ||
preprocessors: ['tokens-studio'], // <-- since 0.16.0 this must be explicit | ||
@@ -113,8 +110,6 @@ platforms: { | ||
sd.cleanAllPlatforms(); | ||
sd.buildAllPlatforms(); | ||
await sd.cleanAllPlatforms(); | ||
await sd.buildAllPlatforms(); | ||
``` | ||
> You can also import as ES Modules if needed. | ||
To run it use the following command | ||
@@ -126,12 +121,9 @@ | ||
> From Style-Dictionary `4.0.0-prerelease.18`, [`transformGroup` and `transforms` can now be combined in a platform inside your config](https://github.com/amzn/style-dictionary/blob/v4/CHANGELOG.md#400-prerelease18). | ||
### Using the preprocessor | ||
If you want to use `excludeParentKeys`, `expand` or allow this package to extract the `fontStyle` from the `fontWeight` e.g. `regular italic`, | ||
you must add the `'tokens-studio'` preprocessor explicitly in the configuration: | ||
You must add the `'tokens-studio'` preprocessor explicitly in the configuration: | ||
```json | ||
{ | ||
"source": ["**/*.tokens.json"], | ||
"source": ["tokens/**/*.json"], | ||
"preprocessors": ["tokens-studio"], | ||
@@ -142,2 +134,36 @@ "platforms": {} | ||
This allows `fontStyles` to be extracted when they are embedded in `fontWeights`, aligns Tokens Studio token types with DTCG token types, and allows excluding parent keys for single-file Tokens Studio exports. | ||
### Using "Expand" | ||
> Expand used to be an sd-transforms exclusive feature but has moved to Style Dictionary itself under a slightly different API. | ||
> This made sense due to object-value tokens being part of the DTCG spec and no longer a Tokens Studio specific feature. | ||
When using the [expand feature of Style Dictionary](https://v4.styledictionary.com/reference/config/#expand) to expand object-value (composite) tokens, | ||
you should pass our additional `expandTypesMap` for Tokens Studio tokens, because these are slightly different from the DTCG tokens: | ||
- shadow tokens are called `boxShadow` and their `offsetX` and `offsetY` props are called `x` and `y` respectively. | ||
- typography tokens have some additional properties in Tokens Studio: | ||
- `paragraphSpacing` -> dimension | ||
- `paragraphIndent` -> dimension | ||
- `textDecoration` -> other | ||
- `textCase` -> other | ||
Due to the Style Dictionary object-value tokens expansion happening before custom preprocessors such as the sd-transforms preprocessor, | ||
which aligns Tokens Studio token types with DTCG token types, this has to be configured like so: | ||
```js | ||
import StyleDictionary from 'style-dictionary'; | ||
import { expandTypesMap } from '@tokens-studio/sd-transforms'; | ||
const sd = new StyleDictionary({ | ||
source: ['tokens/**/*.json'], | ||
preprocessors: ['tokens-studio'], | ||
expand: { | ||
typesMap: expandTypesMap, | ||
}, | ||
platforms: {}, | ||
}); | ||
``` | ||
### Using the transforms | ||
@@ -147,3 +173,3 @@ | ||
{ | ||
"source": ["**/*.tokens.json"], | ||
"source": ["tokens/**/*.json"], | ||
"preprocessors": ["tokens-studio"], | ||
@@ -162,9 +188,9 @@ "platforms": { | ||
}, | ||
"css": { | ||
"scss": { | ||
"transforms": ["ts/size/px", "ts/opacity", "name/kebab"], | ||
"buildPath": "build/css/", | ||
"buildPath": "build/scss/", | ||
"files": [ | ||
{ | ||
"destination": "variables.css", | ||
"format": "css/variables" | ||
"destination": "variables.scss", | ||
"format": "scss/variables" | ||
} | ||
@@ -195,2 +221,3 @@ ] | ||
> [!NOTE] | ||
> From Style-Dictionary `4.0.0-prerelease.18`, [`transformGroup` and `transforms` can now be combined in a platform inside your config](https://github.com/amzn/style-dictionary/blob/v4/CHANGELOG.md#400-prerelease18). | ||
@@ -202,3 +229,3 @@ | ||
```js | ||
import { transforms } from '@tokens-studio/sd-transforms'; | ||
import { getTransforms } from '@tokens-studio/sd-transforms'; | ||
import StyleDictionary from 'style-dictionary'; | ||
@@ -211,22 +238,20 @@ | ||
name: 'custom/tokens-studio', | ||
transforms: [...transforms, 'name/constant'].filter(transform => transform !== 'ts/size/px'), | ||
// default value for platform is css, specifies which Tokens Studio transforms for which platform to grab | ||
transforms: [...getTransforms({ platform: 'css' }), 'name/constant'].filter( | ||
transform => transform !== 'ts/size/px', | ||
), | ||
}); | ||
``` | ||
> Note that you can also manually grab some of the SD built-in transforms by using `StyleDictionary.hooks.transformGroups` or `StyleDictionary.hooks.transforms` | ||
### Options | ||
You can pass options to the `registerTransforms` function. | ||
You can pass options to the `register` function. | ||
```js | ||
registerTransforms(StyleDictionary, { | ||
expand: { | ||
composition: false, | ||
typography: true, | ||
// Note: when using Style-Dictionary v4.0.0-prerelease.2 or higher, filePath no longer gets passed | ||
// as an argument, because preprocessors work on the full dictionary rather than per file (parsers) | ||
border: (token, filePath) => | ||
token.value.width !== 0 && filePath.startsWith(path.resolve('tokens/core')), | ||
shadow: false, | ||
}, | ||
register(StyleDictionary, { | ||
excludeParentKeys: true, | ||
platform: 'css', | ||
name: 'tokens-studio', | ||
'ts/color/modifiers': { | ||
@@ -240,16 +265,15 @@ format: 'hex', | ||
| name | type | required | default | description | | ||
| ----------------------------- | ------------------------ | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | ||
| excludeParentKeys | boolean | ❌ | `false` | Whether or not to exclude parent keys from your token files | | ||
| alwaysAddFontStyle | boolean | ❌ | `false` | Whether or not to always add a 'normal' fontStyle property to typography tokens which do not have explicit fontStyle | | ||
| expand | boolean \| ExpandOptions | ❌ | See props below | `false` to not register the parser at all. By default, expands composition tokens. Optionally, border, shadow and typography as well. | | ||
| expand.composition | boolean \| ExpandFilter | ❌ | `true` | Whether or not to expand compositions. Also allows a filter callback function to conditionally expand per token/filePath | | ||
| expand.typography | boolean \| ExpandFilter | ❌ | `false` | Whether or not to expand typography. Also allows a filter callback function to conditionally expand per token/filePath | | ||
| expand.shadow | boolean \| ExpandFilter | ❌ | `false` | Whether or not to expand shadows. Also allows a filter callback function to conditionally expand per token/filePath | | ||
| expand.border | boolean \| ExpandFilter | ❌ | `false` | Whether or not to expand borders. Also allows a filter callback function to conditionally expand per token/filePath | | ||
| ['ts/color/modifiers'] | ColorModifierOptions | ❌ | See props below | Color modifier options | | ||
| ['ts/color/modifiers'].format | ColorModifierFormat | ❌ | `undefined` | Color modifier output format override ('hex' \| 'hsl' \| 'lch' \| 'p3' \| 'srgb'), uses local format or modifier space as default | | ||
| name | type | required | default | description | | ||
| ----------------------------- | -------------------- | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| excludeParentKeys | boolean | ❌ | `false` | Whether or not to exclude parent keys from your token files | | ||
| platform | `'css'\|'compose'` | ❌ | `css` | Which platform to use the transforms for. | | ||
| name | string | ❌ | `tokens-studio` | Under which name to register the `transformGroup` | | ||
| withSDBuiltins | boolean | ❌ | `true` | Whether to append the Style Dictionary built-in `transformGroup` transforms for the configured platform into the `tokens-studio` transformGroup. | | ||
| alwaysAddFontStyle | boolean | ❌ | `false` | Whether or not to always add a 'normal' fontStyle property to typography tokens which do not have explicit fontStyle | | ||
| ['ts/color/modifiers'] | ColorModifierOptions | ❌ | See props below | Color modifier options | | ||
| ['ts/color/modifiers'].format | ColorModifierFormat | ❌ | `undefined` | Color modifier output format override ('hex' \| 'hsl' \| 'lch' \| 'p3' \| 'srgb'), uses local format or modifier space as default | | ||
> Note: you can also import and use the `parseTokens` function to run the parsing steps on your tokens object manually. | ||
> Handy if you have your own parsers set up (e.g. for JS files), and you want the parser-based features like composites-expansion to work there too. | ||
> [!NOTE] | ||
> You can also import and use the `parseTokens` function to run the parsing steps on your tokens object manually. | ||
> Handy if you have your own preprocessors set up (e.g. for JS files), and you want the preprocessor-based features like composites-expansion to work there too. | ||
@@ -267,7 +291,7 @@ ## Theming | ||
```cjs | ||
import { registerTransforms } from '@tokens-studio/sd-transforms'; | ||
import { register } from '@tokens-studio/sd-transforms'; | ||
import StyleDictionary from 'style-dictionary'; | ||
import { promises } from 'fs'; | ||
registerTransforms(StyleDictionary, { | ||
register(StyleDictionary, { | ||
/* options here if needed */ | ||
@@ -297,7 +321,8 @@ }); | ||
configs.forEach(cfg => { | ||
const sd = StyleDictionary.extend(cfg); | ||
sd.cleanAllPlatforms(); // optionally, cleanup files first.. | ||
sd.buildAllPlatforms(); | ||
}); | ||
async function cleanAndBuild(cfg) { | ||
const sd = new StyleDictionary(cfg); | ||
await sd.cleanAllPlatforms(); // optionally, cleanup files first.. | ||
await sd.buildAllPlatforms(); | ||
} | ||
await Promise.all(configs.map(cleanAndBuild)); | ||
} | ||
@@ -402,7 +427,7 @@ | ||
```js | ||
import { registerTransforms, permutateThemes } from '@tokens-studio/sd-transforms'; | ||
import { register, permutateThemes } from '@tokens-studio/sd-transforms'; | ||
import StyleDictionary from 'style-dictionary'; | ||
import { promises } from 'fs'; | ||
registerTransforms(StyleDictionary, { | ||
register(StyleDictionary, { | ||
/* options here if needed */ | ||
@@ -431,7 +456,8 @@ }); | ||
configs.forEach(cfg => { | ||
const sd = StyleDictionary.extend(cfg); | ||
sd.cleanAllPlatforms(); // optionally, cleanup files first.. | ||
sd.buildAllPlatforms(); | ||
}); | ||
async function cleanAndBuild(cfg) { | ||
const sd = new StyleDictionary(cfg); | ||
await sd.cleanAllPlatforms(); // optionally, cleanup files first.. | ||
await sd.buildAllPlatforms(); | ||
} | ||
await Promise.all(configs.map(cleanAndBuild)); | ||
} | ||
@@ -450,2 +476,4 @@ | ||
Also converts carriage return `\r` into `\n` and `\r\n` into just `\n`. | ||
**matches**: All tokens that have a description property. | ||
@@ -742,7 +770,7 @@ | ||
### ts/typography/css/fontFamily | ||
### ts/shadow/innerShadow | ||
This transforms font-family token values into valid CSS, adding single quotes if necessary. | ||
This transforms shadow tokens to ensure that the `type` property gets converted from `innerShadow` to `inset` (CSS compatible). | ||
**matches**: `token.type` is `'fontFamilies'` | ||
**matches**: `token.type` is `'shadow'` | ||
@@ -754,36 +782,9 @@ #### before | ||
"token": { | ||
"type": "fontFamilies", | ||
"value": "Arial Black, Times New Roman, Foo, sans-serif" | ||
} | ||
} | ||
``` | ||
#### after | ||
```json | ||
{ | ||
"token": { | ||
"type": "fontFamilies", | ||
"value": "'Arial Black', 'Times New Roman', Foo, sans-serif" | ||
} | ||
} | ||
``` | ||
### ts/typography/css/shorthand | ||
This transforms typography tokens into a valid CSS shorthand | ||
**matches**: `token.type` is `'typography'` | ||
#### before | ||
```json | ||
{ | ||
"token": { | ||
"type": "typography", | ||
"type": "color", | ||
"value": { | ||
"fontWeight": "500", | ||
"fontSize": "20px", | ||
"lineHeight": "1.5", | ||
"fontFamily": "Arial" | ||
"offsetX": "0", | ||
"offsetY": "4px", | ||
"blur": "10px", | ||
"color": "#000", | ||
"type": "innerShadow" | ||
} | ||
@@ -799,25 +800,9 @@ } | ||
"token": { | ||
"value": "500 20px/1.5 Arial" | ||
} | ||
} | ||
``` | ||
### ts/shadow/css/shorthand | ||
This transforms shadow tokens into a valid CSS shadow shorthand | ||
**matches**: `token.type` is `'boxShadow'` | ||
#### before | ||
```json | ||
{ | ||
"token": { | ||
"type": "boxShadow", | ||
"type": "color", | ||
"value": { | ||
"x": "5px", | ||
"y": "3px", | ||
"blur": "6px", | ||
"spread": "2px", | ||
"color": "#000000" | ||
"offsetX": "0", | ||
"offsetY": "4px", | ||
"blur": "10px", | ||
"color": "#000", | ||
"type": "inset" | ||
} | ||
@@ -828,43 +813,2 @@ } | ||
#### after | ||
```json | ||
{ | ||
"token": { | ||
"value": "5px 3px 6px 2px #000000" | ||
} | ||
} | ||
``` | ||
### ts/border/css/shorthand | ||
This transforms border tokens into a valid CSS border shorthand | ||
**matches**: `token.type` is `'border'` | ||
#### before | ||
```json | ||
{ | ||
"token": { | ||
"type": "border", | ||
"value": { | ||
"width": "5", | ||
"style": "dashed", | ||
"color": "rgba(#000000, 1)" | ||
} | ||
} | ||
} | ||
``` | ||
#### after | ||
```json | ||
{ | ||
"token": { | ||
"value": "5px dashed rgba(0, 0, 0, 1)" | ||
} | ||
} | ||
``` | ||
## Not sure how to fix your issue? | ||
@@ -871,0 +815,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
7
23
0
1
180253
115
4231
800
1
+ Added@bundled-es-modules/postcss-calc-ast-parser@0.1.6(transitive)
- Removedcolor2k@^2.0.1
- Removeddeepmerge@^4.3.1
- Removedpostcss-calc-ast-parser@^0.1.4
- Removed@isaacs/cliui@8.0.2(transitive)
- Removed@pkgjs/parseargs@0.11.0(transitive)
- Removedansi-regex@5.0.16.1.0(transitive)
- Removedansi-styles@6.2.1(transitive)
- Removedbraces@3.0.3(transitive)
- Removedcolor2k@2.0.3(transitive)
- Removedstring-width@4.2.35.1.2(transitive)
- Removedstrip-ansi@6.0.17.1.0(transitive)
- Removedwrap-ansi@7.0.08.1.0(transitive)