New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@justeat/pie-design-tokens

Package Overview
Dependencies
Maintainers
29
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@justeat/pie-design-tokens - npm Package Compare versions

Comparing version 6.8.1 to 6.8.2

228

build/compileToCss.js
const {
CONSTANTS,
convertGlobalTokenValueToStylesValue,
convertHexValueToHSL,
convertHexValueToRGB,
convertHexValueToHSL,
convertWordToPascalCase,
createRulesForDarkAndHighContrast,
formatLine,
getConvertedShadowsToBoxShadowValues,

@@ -28,11 +30,10 @@ variableGetterFactory,

// This `nesting` variable is used to keep track of the current nesting depth for proper indentation
// Currently when writing to the cssOutput (rather than modeCssOutput) a consistent level of indentation is assumed, so this variable is not used
// More specifically, it is used for adding extra indentation to the 'alternative' modes (e.g. highcontrast and dark) in css and hslColor
let nesting = 0;
const INDENT = ' ';
// Temporary additional CSS output for HSL values of color tokens
const cssOutputHslStart = ':root {\n';
let cssOutputHsl = '';
let modeCssOutputHsl = '';
const cssOutputHslEnd = '}';
const hslColor = {
default: ':root {\n',
// alternate modes are input here (e.g dark and highcontrast)
alternative: '',
};

@@ -58,4 +59,4 @@ /**

hslString += `${cssVarName}-h: ${h};\n`;
hslString += `${INDENT.repeat(nesting || 1)}${cssVarName}-s: ${s}%;\n`; // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
hslString += `${INDENT.repeat(nesting || 1)}${cssVarName}-l: ${l}%;\n`; // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
hslString += formatLine(`${cssVarName}-s: ${s}%;`, 'variable', (nesting || 1)); // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
hslString += formatLine(`${cssVarName}-l: ${l}%;`, 'variable', (nesting || 1)); // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
} else if (!value.endsWith('%') && !value.startsWith('rgb')) {

@@ -69,4 +70,4 @@ // this is an alias token, so point to the correct global token hsl fragments

hslString += `${cssVarName}-h: ${h};\n`;
hslString += `${INDENT.repeat(nesting || 1)}${cssVarName}-s: ${s};\n`; // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
hslString += `${INDENT.repeat(nesting || 1)}${cssVarName}-l: ${l};\n`; // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
hslString += formatLine(`${cssVarName}-s: ${s};`, 'variable', (nesting || 1)); // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
hslString += formatLine(`${cssVarName}-l: ${l};`, 'variable', (nesting || 1)); // Nesting will probably be 0 in the `:root` but we want to indent these lines regardless
}

@@ -76,3 +77,21 @@ return hslString;

/**
* Formats and saves the given `value` to the specified output (css or hslColor and default or alternative).
*
* @param {string} mode - refers to the different modes i.e. default and alternative
* @param {string} value - the value to be formatted and output
* @param {string} output - the object the variables will be output to i.e. 'hslColor' or 'css'
* @returns {string} - formatted string added to it's corresponding output
*
*/
const writeToObject = (mode, value, output) => {
const writtenOutput = ALTERNATE_MODES.includes(mode) ?
output.alternative += formatLine(value, 'variable', nesting, false) :
output.default += formatLine(value, 'variable', 1, false);
return writtenOutput;
};
/**
* Returns a token value using the specified category and name properties passed in.

@@ -149,2 +168,41 @@ * Also handles some special cases (such as rgb format with opacity for colour aliases).

/**
* Creates Shadow Values and outputs them in the correct format
*
* @param {string} value – token value i.e 'style-underline'
* @param {string} category – token category i.e. 'font-caption-link'
* @param {string} name – token name i.e. 'text-decoration'
* @param {string} mode – refers to the different modes i.e. default / dark / highcontrast
* @param {string} output – refers to the different output objects i.e. hslColor / css
*/
const outputShadowValues = (value, category, name, mode, output) => {
// Box shadow definitions
const shadows = getConvertedShadowsToBoxShadowValues(value);
const cssVariable = createCssVariable(category, name, shadows);
writeToObject(mode, cssVariable, output);
};
/**
* Creates String Values and outputs them to their corresponding object
*
* @param {boolean} isAliasToken - checks if token is alias or global
* @param {string} category – token category i.e. 'font-caption-link'
* @param {string} value – token value i.e 'style-underline'
* @param {string} name – token name i.e. 'text-decoration'
* @param {string} mode – refers to the different modes i.e. default / dark / highcontrast
* @param {string} output – refers to the different output objects i.e. hslColor / css
* @return {string} compiledValue based on if token is alias or global
*/
const outputStringValue = (isAliasToken, category, value, name, mode, output) => {
// If we're parsing an alias, we need to do some replacement based on its global value
const compiledValue = isAliasToken
? convertAliasToValue(category, value)
: convertGlobalTokenValueToStylesValue(category, value);
const cssVariable = createCssVariable(category, name, compiledValue, mode);
writeToObject(mode, cssVariable, output);
return compiledValue;
};
/**
* Takes a given set of tokens and loops through the key/value pairs creating valid CSS variables

@@ -158,2 +216,3 @@ * If the token value is an object, then this function will be called recursively until a string value is found.

* @param {object} tokens - An object containing a subset of tokens to drill down into
* @param {object} output - The object that all css tokens, headings and rules will be output to
* @param {boolean} isAliasToken - If true, the alias value should be replaced by a reference to the global value when compiled.

@@ -163,12 +222,5 @@ * @param {string} mode - Used when calling the function recursively. If the current token's value is an object, pass the token's name here.

* under a custom CSS rule and/or `@media` query.
* @returns {[string, string]} – Two valid CSS strings containing tokens compiled from the `tokens` object.
* The first string contains CSS to be written in the `'default'` mode.
* The second string contains CSS to be written in any alternate modes.
* @returns {object} – An updated css `output` object containing all the compiled tokens, separated by `default` and `alternative`.
*/
const parseTokens = (theme, category, tokens, isAliasToken = false, mode = 'default') => {
let cssOutput = '';
let modeCssOutput = ''; // Use a separate output for the alternate modes so they can be written to the file separate from `:root`.
// Loop through tokens in this object
// When we look inside the object, if we find key/value pairs, then turn into variables
// If we find another object, then we send that object back into this function to be parsed
const parseTokens = (theme, category, tokens, output, isAliasToken = false, mode = 'default') => {
tokens.forEach(([name, value]) => {

@@ -178,15 +230,4 @@ if (value === null) return; // continue

if (typeof value === 'string') {
// If we're parsing an alias, we need to do some replacement based on its global value
const compiledValue = isAliasToken
? convertAliasToValue(category, value)
: convertGlobalTokenValueToStylesValue(category, value);
const compiledValue = outputStringValue(isAliasToken, category, value, name, mode, output);
const cssVariable = createCssVariable(category, name, compiledValue, mode);
if (ALTERNATE_MODES.includes(mode)) {
// Write CSS for alternate modes to a different object
modeCssOutput += `${INDENT.repeat(nesting)}${cssVariable}`;
} else {
cssOutput += `${INDENT}${cssVariable}`;
}
// HSL output

@@ -196,8 +237,3 @@ if (category === 'color') {

if (cssVariableHsl.length) {
if (ALTERNATE_MODES.includes(mode)) {
// Write HSL CSS for alternate modes to a different object
modeCssOutputHsl += `${INDENT.repeat(nesting)}${cssVariableHsl}`;
} else {
cssOutputHsl += `${INDENT}${cssVariableHsl}`;
}
writeToObject(mode, cssVariableHsl, hslColor);
}

@@ -207,11 +243,3 @@ }

if (value.shadows) {
// Box shadow definitions
const shadows = getConvertedShadowsToBoxShadowValues(value.shadows);
const cssVariable = createCssVariable(category, name, shadows);
if (ALTERNATE_MODES.includes(mode)) {
modeCssOutput += `${INDENT.repeat(nesting)}${cssVariable}`;
} else {
cssOutput += `${INDENT}${cssVariable}`;
}
outputShadowValues(value.shadows, category, name, mode, output);
}

@@ -222,45 +250,35 @@

if (!category.includes('elevation') || ALTERNATE_MODES.includes(name)) {
const heading = `/* ${convertWordToPascalCase(name)} ${category} theme */\n`;
const heading = `${convertWordToPascalCase(name)} ${category} theme`;
if (ALTERNATE_MODES.includes(mode) || ALTERNATE_MODES.includes(name)) {
// Write CSS for alternate modes to a different object
modeCssOutput += `${INDENT.repeat(nesting)}${heading}`;
output.alternative += formatLine(heading, 'heading', nesting);
} else {
cssOutput += `${INDENT}${heading}`;
output.default += formatLine(heading, 'heading');
}
}
// Dark and high contrast mode tokens require additional CSS rules which introduce additional nesting.
// When opening a new pair of curly braces, make sure to increment the `nesting` variable.
// The curly braces will be automatically closed by the `while` loop below.
// Note that the order of nesting is important for css. @media should be first.
if (CATEGORIES_WITH_ALTERNATE_MODES.includes(category)) {
const isDark = ['dark', 'highcontrast-dark'].includes(name);
const isHighContrast = ['highcontrast', 'highcontrast-dark'].includes(name);
let cssRule = '';
let mediaQuery = '';
// adds line-height css variables to alias tokens
if (category.includes('font') && isAliasToken) {
Object.keys(value).forEach((key) => {
if (key === 'size--wide' || key === 'size--narrow' || key === 'size') {
const lineHeight = `line-height-${key}`;
if (isDark && isHighContrast) {
cssRule = 'html[data-darkmode-enabled][data-highcontrast-enabled]';
mediaQuery = '@media (prefers-color-scheme: dark)';
} else if (isDark) {
cssRule = 'html[data-darkmode-enabled]';
mediaQuery = '@media (prefers-color-scheme: dark)';
} else if (isHighContrast) {
cssRule = 'html[data-highcontrast-enabled]';
}
value[lineHeight.replace('-size', '')] = `${value[key]}-line-height`;
}
});
}
if (CATEGORIES_WITH_ALTERNATE_MODES.includes(category)) {
const [mediaQuery, cssRule] = createRulesForDarkAndHighContrast(name);
if (mediaQuery.length) {
const openMediaQuery = `${INDENT.repeat(nesting)}${mediaQuery} {\n`;
modeCssOutput += openMediaQuery;
output.alternative += formatLine(mediaQuery, 'rule', nesting);
if (category === 'color') {
modeCssOutputHsl += openMediaQuery;
hslColor.alternative += formatLine(mediaQuery, 'rule', nesting);
}
nesting++;
}
if (cssRule.length) {
const openCssRule = `${INDENT.repeat(nesting)}${cssRule} {\n`;
modeCssOutput += openCssRule;
output.alternative += formatLine(cssRule, 'rule', nesting);
if (category === 'color') {
modeCssOutputHsl += openCssRule;
hslColor.alternative += formatLine(cssRule, 'rule', nesting);
}

@@ -271,20 +289,6 @@ nesting++;

// adds line-height css variables to alias tokens
if (category.includes('font') && isAliasToken) {
Object.keys(value).forEach((key) => {
if (key === 'size--wide' || key === 'size--narrow' || key === 'size') {
const lineHeight = `line-height-${key}`;
value[lineHeight.replace('-size', '')] = `${value[key]}-line-height`;
}
});
}
// When processing the different modes, the category shouldn't have the mode name appended
// because we don't want the variable names to be unique
const updatedCategoryName = ['default', ...ALTERNATE_MODES].includes(name) ? category : `${category}-${name}`;
const [css, modeCss] = parseTokens(theme, updatedCategoryName, Object.entries(value), isAliasToken, name);
cssOutput += css;
modeCssOutput += modeCss;
parseTokens(theme, updatedCategoryName, Object.entries(value), output, isAliasToken, name);

@@ -294,5 +298,5 @@ // Close any unclosed curly braces

nesting--;
modeCssOutput += `${INDENT.repeat(nesting)}}\n`;
output.alternative += formatLine('', 'closingLine', nesting);
if (category === 'color') {
modeCssOutputHsl += `${INDENT.repeat(nesting)}}\n`;
hslColor.alternative += formatLine('', 'closingLine', nesting);
}

@@ -302,3 +306,4 @@ }

});
return [cssOutput, modeCssOutput];
return output;
};

@@ -311,9 +316,11 @@

* @param {object} themeTokens – Theme object subset of the entire design token object (for example, the jet theme object or skip theme object)
* @returns {string} – A valid CSS string, compiled from the `themeTokens` object
* @returns {object} – A valid css object, compiled from the `themeTokens` object
*/
const createCssFromTheme = (theme, themeTokens) => {
const categoryKeys = Object.keys(themeTokens);
let cssOutput = ':root {\n';
let modeCssOutput = '';
const css = {
default: ':root {\n',
// alternate modes are input here (e.g dark and highcontrast modes)
alternative: '',
};
currentThemeTokens = themeTokens;

@@ -328,7 +335,4 @@

const categoryGlobals = Object.entries(themeTokens[category][GLOBAL_TOKEN_KEY]);
const [css, modeCss] = parseTokens(theme, category, categoryGlobals);
cssOutput += `${INDENT}/* Global tokens - ${categoryName} */\n`;
cssOutput += css;
modeCssOutput += modeCss;
css.default += formatLine(`Global tokens - ${categoryName}`, 'heading');
parseTokens(theme, category, categoryGlobals, css);
}

@@ -339,12 +343,8 @@

const categoryAliases = Object.entries(themeTokens[category][ALIAS_TOKEN_KEY]);
const [css, modeCss] = parseTokens(theme, category, categoryAliases, true);
cssOutput += `${INDENT}/* Alias tokens - ${categoryName} */\n`;
cssOutput += css;
modeCssOutput += modeCss;
css.default += formatLine(`Alias tokens - ${categoryName}`, 'heading');
parseTokens(theme, category, categoryAliases, css, true);
}
});
cssOutput += '}';
return [cssOutput, modeCssOutput];
return css;
};

@@ -370,7 +370,5 @@

themeKeys.forEach((themeKey) => {
const [cssString, modeCssString] = createCssFromTheme(themeKey, tokens.theme[themeKey]);
writeToFile(themeKey, 'css', `${cssString}\n${modeCssString}`);
const hslOutput = cssOutputHslStart + cssOutputHsl + cssOutputHslEnd;
writeToFile(`${themeKey}-hsl-colors`, 'css', `${hslOutput}\n${modeCssOutputHsl}`);
const css = createCssFromTheme(themeKey, tokens.theme[themeKey]);
writeToFile(themeKey, 'css', `${css.default}}\n${css.alternative}`);
writeToFile(`${themeKey}-hsl-colors`, 'css', `${hslColor.default}}\n${hslColor.alternative}`);
});

@@ -377,0 +375,0 @@ return true;

@@ -6,5 +6,7 @@ const {

convertWordToPascalCase,
createRulesForDarkAndHighContrast,
getConvertedShadowsToBoxShadowValues,
formatLine,
variableGetterFactory,
writeToFile,
variableGetterFactory,
} = require('./helpers');

@@ -27,3 +29,2 @@

let nesting = 0;
const INDENT = ' ';

@@ -97,3 +98,3 @@ /**

return `${INDENT.repeat(nesting)}${getScssVarValue(shortenedVar)}: ${compiledValue};\n`;
return formatLine(`${getScssVarValue(shortenedVar)}: ${compiledValue};`, 'variable', nesting);
};

@@ -140,21 +141,6 @@

// Dark mode tokens require additional CSS rules which introduce nesting.
// When opening a new pair of curly braces, make sure to increment the `nesting` variable.
const isDark = name.includes('dark');
const isHighContrast = name.includes('highcontrast');
let cssRule = '';
let mediaQuery = '';
const [mediaQuery, cssRule] = createRulesForDarkAndHighContrast(name);
if (isDark && isHighContrast) {
cssRule = 'html[data-darkmode-enabled][data-highcontrast-enabled]';
mediaQuery = '@media (prefers-color-scheme: dark)';
} else if (isDark) {
cssRule = 'html[data-darkmode-enabled]';
mediaQuery = '@media (prefers-color-scheme: dark)';
} else if (isHighContrast) {
cssRule = 'html[data-highcontrast-enabled]';
}
if (mediaQuery.length) {
scssOutput += `${INDENT.repeat(nesting)}${mediaQuery} {\n`;
scssOutput += formatLine(mediaQuery, 'rule', nesting);
nesting++;

@@ -164,3 +150,3 @@ }

if (cssRule.length) {
scssOutput += `${INDENT.repeat(nesting)}${cssRule} {\n`;
scssOutput += formatLine(cssRule, 'rule', nesting);
nesting++;

@@ -186,3 +172,3 @@ }

nesting--;
scssOutput += `${INDENT.repeat(nesting)}}\n`;
scssOutput += formatLine('', 'closingLine', nesting);
}

@@ -189,0 +175,0 @@ }

@@ -33,2 +33,26 @@ const fs = require('fs');

/**
* Establishes a pattern for our line formats i.e. headings / values / rules with clear indentation
* so if patterns are needed, they can be formed more easily.
*
* @param {string} value – the content displayed by the line
* @param {string} textType – the type of text i.e. 'heading', 'variable'
* @param {number} nestAmount – how much nesting is required - defaults to 1
* @param {boolean} newLine – specifies whether a new line is needed
* @param {boolean} indent – the indent for each line
* @returns {string} - formatted line
*/
const formatLine = (value = '', textType, nestAmount = 1, newLine = true, indent = ' ') => {
const text = {
heading: `${indent.repeat(nestAmount)}/* ${value} */`,
variable: `${indent.repeat(nestAmount)}${value}`,
rule: `${indent.repeat(nestAmount)}${value} {`,
closingLine: `${indent.repeat(nestAmount)}}`,
};
if (!(textType in text)) return ('Please specify textType');
return `${text[textType]}${newLine ? '\n' : ''}`;
};
/**
* Loops through each theme and adds the tokens found in `tokens.global` to each individual theme object.

@@ -270,2 +294,31 @@ *

/**
* Creates the additional CSS and mediaQuery rules needed for dark and high contrast mode.
*
* @param {string} name – name of token
* @returns {[string, string]} – Two valid strings -
* The first string contains the mediaQuery variable
* The second string contains the cssRule variable
*/
const createRulesForDarkAndHighContrast = (name) => {
const isDark = name.includes('dark');
const isHighContrast = name.includes('highcontrast');
let cssRule = '';
let mediaQuery = '';
if (isDark && isHighContrast) {
cssRule = 'html[data-darkmode-enabled][data-highcontrast-enabled]';
mediaQuery = '@media (prefers-color-scheme: dark)';
} else if (isDark) {
cssRule = 'html[data-darkmode-enabled]';
mediaQuery = '@media (prefers-color-scheme: dark)';
} else if (isHighContrast) {
cssRule = 'html[data-highcontrast-enabled]';
}
return [mediaQuery, cssRule];
};
// /**

@@ -315,5 +368,7 @@ // * Deprecated – will be converted to support platform value replacement in later PR

convertWordToPascalCase,
createRulesForDarkAndHighContrast,
getConvertedShadowsToBoxShadowValues,
formatLine,
variableGetterFactory,
writeToFile,
};

@@ -8,2 +8,4 @@ const {

convertHexValueToHSL,
createRulesForDarkAndHighContrast,
formatLine,
variableGetterFactory,

@@ -128,2 +130,86 @@ } = require('../helpers');

describe('formatLine', () => {
it('should format line in accordance with the "heading" textType', () => {
// Arrange
const line = 'This is a heading';
const textType = 'heading';
const nestAmount = 1;
const newLine = false;
// Act
const result = formatLine(line, textType, nestAmount, newLine);
// Assert
expect(result).toBe(' /* This is a heading */');
});
it('should return instruction when no textType is selected', () => {
// Arrange
const line = 'value';
const nestAmount = 1;
const newLine = false;
// Act
const result = formatLine(line, '', nestAmount, newLine);
// Assert
expect(result).toBe('Please specify textType');
});
it('should return rule with open bracket when "rule" textType is selected', () => {
// Arrange
const line = 'value';
const nestAmount = 1;
const textType = 'rule';
const newLine = false;
// Act
const result = formatLine(line, textType, nestAmount, newLine);
// Assert
expect(result).toBe(' value {');
});
it('should add closing bracket with indentation when "closing line" is selected', () => {
// Arrange
const nestAmount = 1;
const textType = 'closingLine';
const newLine = false;
// Act
const result = formatLine('', textType, nestAmount, newLine);
// Assert
expect(result).toBe(' }');
});
it('should indent the line as many times as specified by the nest amount', () => {
// Arrange
const indent = ' ';
const value = '--dt-color-blue-light-hc: #8bbcfe;';
const nestAmount = 2;
const textType = 'variable';
const newLine = false;
// Act
const result = formatLine(value, textType, nestAmount, newLine, indent);
// Assert
expect(result).toBe(' --dt-color-blue-light-hc: #8bbcfe;');
});
});
describe('createRulesForDarkAndHighContrast', () => {
it.each([
[['default'], ['', '']],
[['dark'], ['@media (prefers-color-scheme: dark)', 'html[data-darkmode-enabled]']],
[['highcontrast'], ['', 'html[data-highcontrast-enabled]']],
[['default', 'highcontrast-dark', 'dark'], ['@media (prefers-color-scheme: dark)', 'html[data-darkmode-enabled]']]])('should return corresponding rules based on the name provided', (name, expected) => {
// Act
const result = createRulesForDarkAndHighContrast(name, expected);
// Assert
expect(result).toStrictEqual(expected);
});
});
describe('convertGlobalTokenValueToStylesValue', () => {

@@ -130,0 +216,0 @@ it('should separate pipe-delimited font values', () => {

@@ -2095,3 +2095,3 @@ {

},
"version": "6.8.1"
"version": "6.8.2"
}
{
"name": "@justeat/pie-design-tokens",
"version": "6.8.1",
"version": "6.8.2",
"description": "Design Tokens for the PIE Component System",

@@ -5,0 +5,0 @@ "main": "index.js",

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc