All files / packages/icons/scripts generate-changes.ts

0% Statements 0/58
0% Branches 0/22
0% Functions 0/18
0% Lines 0/51

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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185                                                                                                                                                                                                                                                                                                                                                                                 
/**
 * Generate changes module
 * Pure generators for content strings with no file I/O side effects
 * Generates bg-{type}.yml and icon.type.css content
 */
 
import type { ParsedIcon } from './csv-parser.js';
 
export type ChangeType = 'slds' | 'sds';
 
export interface SldsChanges {
  bgStandard: string | null;
  bgActions: string | null;
  releaseNotes: string;
}
 
export interface SdsChanges {
  iconTypeCss: string;
}
 
/**
 * Generate SLDS changes (bg-*.yml files and release notes)
 * @param icons - Array of parsed icons
 * @returns Object with content strings for bg-standard.yml, bg-actions.yml, and releasenotes.md
 */
export function generateSldsChanges(icons: ParsedIcon[]): SldsChanges {
  const standardIcons = icons.filter((icon) => icon.icon_type === 'standard');
  const actionIcons = icons.filter((icon) => icon.icon_type === 'action');
 
  const bgStandard = standardIcons.length > 0 ? generateBgYml(standardIcons, 'standard') : null;
 
  const bgActions = actionIcons.length > 0 ? generateBgYml(actionIcons, 'actions') : null;
 
  const releaseNotes = generateReleaseNotes(icons);
 
  return {
    bgStandard,
    bgActions,
    releaseNotes,
  };
}
 
/**
 * Generate bg-*.yml content for SLDS
 * @param icons - Array of icons of the same type
 * @param iconType - 'standard' or 'actions'
 * @returns YAML content string
 */
function generateBgYml(icons: ParsedIcon[], iconType: 'standard' | 'actions'): string {
  const disclaimer = `# Copy the below content to design-system-internal/design-tokens/bg-${iconType}.yml\n\n`;
 
  const iconsContent = icons
    .map((icon) => {
      const key =
        icon.icon_type === 'action' ? `ACTION_${icon.icon_name.toUpperCase()}` : icon.icon_name.toUpperCase();
 
      const colorHex = (icon.color_hex || '').toUpperCase();
 
      return `  ${key}:\n    value: '${colorHex}'`;
    })
    .join('\n');
 
  return disclaimer + iconsContent;
}
 
/**
 * Generate release notes content
 * @param icons - Array of parsed icons
 * @returns Release notes markdown content
 */
function generateReleaseNotes(icons: ParsedIcon[]): string {
  const disclaimer = `<!-- RELEASENOTES.md -->\n\n`;
 
  const iconsByType = icons.reduce(
    (group, icon) => {
      const type = icon.icon_type;
      if (!group[type]) {
        group[type] = [];
      }
      group[type].push(icon.icon_name);
      return group;
    },
    {} as Record<string, string[]>,
  );
 
  const releaseNotesContent = Object.entries(iconsByType)
    .map(([type, iconNames]) => {
      const typeCapitalized = type.charAt(0).toUpperCase() + type.slice(1);
      const iconList = iconNames.map((iconName) => `  - Added ${iconName}`).join('\n');
      return `- ${typeCapitalized} set\n${iconList}`;
    })
    .join('\n');
 
  return disclaimer + releaseNotesContent;
}
 
/**
 * Generate SDS changes (icon.type.css)
 * @param icons - Array of parsed icons
 * @returns Object with CSS content string
 */
export function generateSdsChanges(icons: ParsedIcon[]): SdsChanges {
  const standardIcons = icons.filter((icon) => icon.icon_type === 'standard');
  const actionIcons = icons.filter((icon) => icon.icon_type === 'action');
 
  const combinedIcons = [...standardIcons, ...actionIcons];
 
  const iconTypeCss = generateIconTypeCss(combinedIcons);
 
  return {
    iconTypeCss,
  };
}
 
/**
 * Generate icon.type.css content for SDS
 * @param icons - Array of standard and action icons
 * @returns CSS content string
 */
function generateIconTypeCss(icons: ParsedIcon[]): string {
  const disclaimer = `/* Copy the below content to sds/packages/sds-subsystems/src/slds+/icon/icon.type.css */\n\n`;
 
  const iconsContent = icons
    .map((icon) => {
      const className = `.slds-icon-${icon.icon_type}-${icon.icon_name.replaceAll('_', '-')}`;
      const rgbColor = hexToRgb(icon.color_hex ?? null);
 
      return `  ${className} {\n    --slds-c-icon-color-background: ${rgbColor};\n  }`;
    })
    .join('\n');
 
  return disclaimer + iconsContent;
}
 
/**
 * Convert hex color to RGB format
 * @param hex - Hex color string (e.g., "#1b96ff" or "1b96ff")
 * @returns RGB color string (e.g., "rgb(27, 150, 255)") or empty string if invalid
 */
export function hexToRgb(hex: string | null): string {
  if (!hex) {
    return '';
  }
 
  // Remove # if present
  let cleanHex = hex;
  if (cleanHex[0] === '#') {
    cleanHex = cleanHex.slice(1);
  }
 
  // Validate hex format
  if (!/^[0-9A-Fa-f]{6}$/.test(cleanHex)) {
    return '';
  }
 
  // Parse RGB components
  const r = parseInt(cleanHex.slice(0, 2), 16);
  const g = parseInt(cleanHex.slice(2, 4), 16);
  const b = parseInt(cleanHex.slice(4, 6), 16);
 
  return `rgb(${r}, ${g}, ${b})`;
}
 
/**
 * Generate metadata JSON content for an icon
 * @param icon - Parsed icon object
 * @returns JSON content string
 */
export function generateMetadataJson(icon: ParsedIcon): string {
  return `{\n  "synonyms": ${JSON.stringify(icon.synonyms).replace(/,/g, ', ')}\n}`;
}
 
/**
 * Sort icons by icon type
 * @param icons - Array of parsed icons
 * @returns Sorted array of icons
 */
export function sortByIconType(icons: ParsedIcon[]): ParsedIcon[] {
  return icons.sort((i1, i2) => {
    if (i1.icon_type < i2.icon_type) return -1;
    if (i1.icon_type > i2.icon_type) return 1;
    return 0;
  });
}