UNPKG

sparkle-design-cli

Version:

Sparkle Design CSS Generator - デザインシステムCSSを設定ファイルから生成するツール

111 lines (94 loc) 3.66 kB
/** * カラー変換ユーティリティ */ import { oklch } from 'culori'; import { COLOR_PRECISION, GRAY_LEVEL_MAP, MESSAGES } from './constants.js'; /** * 16進数カラーをrgba形式に変換 * @param {string} hex 16進数のカラーコード(#付きまたは無し) * @returns {string} rgba形式の文字列 */ export function hexToRgba(hex) { // #を削除 let cleanHex = hex.replace('#', ''); // 3桁の場合は6桁に拡張 if (cleanHex.length === 3) { cleanHex = cleanHex .split('') .map((char) => char + char) .join(''); } const r = parseInt(cleanHex.substring(0, 2), 16); const g = parseInt(cleanHex.substring(2, 4), 16); const b = parseInt(cleanHex.substring(4, 6), 16); return `rgba(${r}, ${g}, ${b}, 1)`; } /** * 16進数カラーをOKLCH形式に変換 * @param {string} hex 16進数のカラーコード(#付きまたは無し) * @returns {string} OKLCH形式の文字列 */ export function hexToOklch(hex) { // #を削除 const cleanHex = hex.replace('#', ''); // 3桁の場合は6桁に、4桁の場合は8桁に拡張 let fullHex = cleanHex; if (cleanHex.length === 3 || cleanHex.length === 4) { fullHex = cleanHex .split('') .map((char) => char + char) .join(''); } // culoriを使用してHEXからOKLCHに変換 const oklchColor = oklch(`#${fullHex}`); if (!oklchColor) { console.warn(MESSAGES.COLOR_CONVERSION_FAILED(hex)); return `oklch(0 0 0)`; } // 精度を調整して出力 const l = Math.round((oklchColor.l || 0) * COLOR_PRECISION.OKLCH_L) / COLOR_PRECISION.OKLCH_L; const c = Math.round((oklchColor.c || 0) * COLOR_PRECISION.OKLCH_C) / COLOR_PRECISION.OKLCH_C; const h = oklchColor.h ? Math.round(oklchColor.h * COLOR_PRECISION.OKLCH_H) / COLOR_PRECISION.OKLCH_H : 0; // アルファ値がある場合(1未満の場合のみ出力に追加) if (oklchColor.alpha !== undefined && oklchColor.alpha < 1) { const a = Math.round(oklchColor.alpha * COLOR_PRECISION.OKLCH_ALPHA) / COLOR_PRECISION.OKLCH_ALPHA; return `oklch(${l} ${c} ${h} / ${a})`; } return `oklch(${l} ${c} ${h})`; } /** * 色のトークンを生成する * @param {Object} colors colors.jsonから読み込んだ色の定義 * @param {Object} grayMapping gray.jsonから読み込んだグレーの定義 * @param {string} primaryColor プライマリカラーの名前 * @returns {string} 色のトークンのCSS文字列 */ export function generateColorTokens(colors, grayMapping, primaryColor) { const colorTokens = []; // 通常の色トークンを生成 Object.entries(colors).forEach(([colorName, colorValues]) => { if (typeof colorValues === 'object' && colorValues !== null) { Object.entries(colorValues).forEach(([level, hexValue]) => { const oklchValue = hexToOklch(hexValue); colorTokens.push(` --color-${colorName}-${level}: ${oklchValue};`); }); } else if (typeof colorValues === 'string') { // black, white, web-focusなどの単色 const oklchValue = hexToOklch(colorValues); colorTokens.push(` --color-${colorName}: ${oklchValue};`); } }); // グレーの色トークンを生成(プライマリカラーに基づく) if (primaryColor && grayMapping[primaryColor]) { const grayColors = grayMapping[primaryColor]; Object.entries(grayColors).forEach(([key, hexValue]) => { const grayLevel = GRAY_LEVEL_MAP[key] || key; const oklchValue = hexToOklch(hexValue); colorTokens.push(` --color-gray-${grayLevel}: ${oklchValue};`); }); } return colorTokens.join('\n'); }