Skip to main content
Glama
1yhy
by 1yhy
css.ts6.18 kB
/** * CSS Utilities * * CSS output optimization and generation utilities. * Used to reduce output size and improve readability. * * @module utils/css */ // ==================== CSS Shorthand Generation ==================== /** * Generate CSS shorthand properties (such as padding, margin, border-radius) * * @example * generateCSSShorthand({ top: 10, right: 10, bottom: 10, left: 10 }) // "10px" * generateCSSShorthand({ top: 10, right: 20, bottom: 10, left: 20 }) // "10px 20px" */ export function generateCSSShorthand( values: { top: number; right: number; bottom: number; left: number; }, options: { ignoreZero?: boolean; suffix?: string; } = {}, ): string | undefined { const { ignoreZero = true, suffix = "px" } = options; const { top, right, bottom, left } = values; if (ignoreZero && top === 0 && right === 0 && bottom === 0 && left === 0) { return undefined; } if (top === right && right === bottom && bottom === left) { return `${top}${suffix}`; } if (right === left) { if (top === bottom) { return `${top}${suffix} ${right}${suffix}`; } return `${top}${suffix} ${right}${suffix} ${bottom}${suffix}`; } return `${top}${suffix} ${right}${suffix} ${bottom}${suffix} ${left}${suffix}`; } // ==================== Numeric Precision Optimization ==================== /** * Round a number to specified precision * @param value Original number * @param precision Number of decimal places, default 0 (integer) */ export function roundValue(value: number, precision: number = 0): number { if (precision === 0) { return Math.round(value); } const multiplier = Math.pow(10, precision); return Math.round(value * multiplier) / multiplier; } /** * Format px value, rounded to integer * @param value Pixel value */ export function formatPxValue(value: number): string { return `${Math.round(value)}px`; } /** * Format numeric value, used for gap and other properties, rounded to integer * @param value Numeric value */ export function formatNumericValue(value: number): string { return `${Math.round(value)}px`; } // ==================== Browser Defaults ==================== /** * Browser/Tailwind default values * These values can be omitted from output */ export const BROWSER_DEFAULTS: Record<string, string | number | undefined> = { // Text defaults textAlign: "left", verticalAlign: "top", fontWeight: 400, // Flex defaults flexDirection: "row", justifyContent: "flex-start", alignItems: "stretch", // Position defaults (if all elements are absolute, can be omitted) // position: 'static', // Not omitting for now, as we explicitly use absolute // Other opacity: "1", borderStyle: "none", }; /** * Check if a value is the default value */ export function isDefaultValue(key: string, value: string | number | undefined): boolean { if (value === undefined) return true; const defaultValue = BROWSER_DEFAULTS[key]; if (defaultValue === undefined) return false; // Handle number and string comparison if (typeof defaultValue === "number" && typeof value === "number") { return defaultValue === value; } return String(defaultValue) === String(value); } /** * Omit default style values * @param styles CSS style object * @returns Optimized style object */ export function omitDefaultStyles<T extends Record<string, unknown>>(styles: T): Partial<T> { const result: Partial<T> = {}; for (const [key, value] of Object.entries(styles)) { // Skip undefined if (value === undefined) continue; // Skip default values if (isDefaultValue(key, value as string | number)) continue; // Keep non-default values (result as Record<string, unknown>)[key] = value; } return result; } // ==================== Gap Analysis ==================== /** * Analyze gap consistency * @param gaps Array of gaps * @param tolerancePercent Tolerance percentage, default 20% */ export function analyzeGapConsistency( gaps: number[], tolerancePercent: number = 20, ): { isConsistent: boolean; averageGap: number; roundedGap: number; variance: number; } { if (gaps.length === 0) { return { isConsistent: true, averageGap: 0, roundedGap: 0, variance: 0 }; } if (gaps.length === 1) { const rounded = roundValue(gaps[0]); return { isConsistent: true, averageGap: gaps[0], roundedGap: rounded, variance: 0 }; } // Calculate average const avg = gaps.reduce((a, b) => a + b, 0) / gaps.length; // Calculate variance const variance = gaps.reduce((sum, gap) => sum + Math.pow(gap - avg, 2), 0) / gaps.length; const stdDev = Math.sqrt(variance); // Determine consistency: standard deviation less than specified percentage of average const tolerance = avg * (tolerancePercent / 100); const isConsistent = stdDev <= tolerance; // Round to integer const roundedGap = roundValue(avg); return { isConsistent, averageGap: avg, roundedGap, variance }; } /** * Round gap to common values * Common values: 0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 64 */ export function roundToCommonGap(gap: number): number { const COMMON_GAPS = [0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128]; // Find closest common value let closest = COMMON_GAPS[0]; let minDiff = Math.abs(gap - closest); for (const commonGap of COMMON_GAPS) { const diff = Math.abs(gap - commonGap); if (diff < minDiff) { minDiff = diff; closest = commonGap; } } // If difference is too large (over 4px), use rounded value if (minDiff > 4) { return roundValue(gap); } return closest; } // ==================== Export Info Optimization ==================== /** * Optimize exportInfo, omit nodeId if it's the same as node id */ export function optimizeExportInfo( nodeId: string, exportInfo: { type: string; format: string; nodeId?: string; fileName?: string }, ): { type: string; format: string; nodeId?: string; fileName?: string } { const result = { ...exportInfo }; // If nodeId is the same as node id, omit it if (result.nodeId === nodeId) { delete result.nodeId; } return result; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/1yhy/Figma-Context-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server