All files / packages/design-tokens/src/style-dictionary/formats css-config.js

100% Statements 25/25
96.42% Branches 27/28
100% Functions 4/4
100% Lines 25/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81                    2x 18x   18x 1x     17x   17x     19x 19x 2x       19x     19x     19x 2x             17x 2x             15x 1x           14x 5x     14x     12x   12x               2x 21x   18x      
/**
 * CSS Config format for generating config.css
 * Config tokens are configuration flags that are theme-independent
 */
 
/**
 * Format configuration tokens as CSS custom properties
 * @param {Object} dictionary - Style Dictionary token dictionary
 * @returns {string} Formatted CSS output
 */
const cssConfigFormatter = (dictionary) => {
  const tokens = dictionary.allTokens;
 
  if (tokens.length === 0) {
    return '/** This file is generated. Do not edit manually. **/\n:root {\n}\n';
  }
 
  let output = '/** This file is generated. Do not edit manually. **/\n:root {\n';
 
  tokens.forEach((token) => {
    // Add comment from token metadata
    // Check original first (preserves source), then transformed token as fallback
    const comment = token.original?.$description || token.$description;
    if (comment) {
      output += `  /* ${comment} */\n`;
    }
 
    // Convert token path to CSS variable name (e.g., slds.is.v2.enabled → --slds-is-v2-enabled)
    const tokenName = token.path.join('-');
 
    // Get value with fallback chain (prefer original untransformed value)
    let value = token.original?.$value ?? token.$value ?? token.value;
 
    // Validate value type - config tokens must be primitives
    if (value === undefined || value === null) {
      throw new Error(
        `Config token '${tokenName}' has ${value === undefined ? 'undefined' : 'null'} value. ` +
          `Check the token definition in tokens/common/config.json`,
      );
    }
 
    // Validate object values
    if (typeof value === 'object') {
      throw new Error(
        `Config token '${tokenName}' has ${Array.isArray(value) ? 'array' : 'object'} value. ` +
          `Config tokens must be primitives (string, number, or boolean).`,
      );
    }
 
    // Validate empty strings
    if (typeof value === 'string' && value.trim() === '') {
      throw new Error(
        `Config token '${tokenName}' has empty string value. ` + `Config tokens require meaningful values.`,
      );
    }
 
    // Format value: primitives output as-is, strings get quotes (except 'true'/'false')
    if (typeof value === 'string' && value !== 'true' && value !== 'false') {
      value = `"${value}"`;
    }
 
    output += `  --${tokenName}: ${value};\n`;
  });
 
  output += '}\n';
 
  return output;
};
 
/**
 * Registers the CSS config format with Style Dictionary
 * Used in build.js to generate dist/config/config.css
 * @param {StyleDictionary} StyleDictionary - Style Dictionary instance
 */
export const cssConfigFormat = (StyleDictionary) => {
  StyleDictionary.registerFormat({
    name: 'css/config',
    format: ({ dictionary }) => cssConfigFormatter(dictionary),
  });
};