@wix/css-property-parser
Version:
A comprehensive TypeScript library for parsing and serializing CSS property values with full MDN specification compliance
198 lines (197 loc) • 9.08 kB
JavaScript
// =============================================================================
// CSS Property Parser - Modern Type Definitions
// =============================================================================
// Clean, modern type system without legacy components
// Follows MDN specifications with strict keyword typing
//
// CRITICAL RULE: ALL TYPES MUST BE DEFINED IN THIS FILE
// - No type definitions in individual evaluators
// - All evaluators must import types from this centralized location
// - This ensures consistency and prevents type conflicts
//
// SHARED EVALUATOR RULE: Same Root Type = Single Evaluator
// - When MDN properties share the same root type pattern (e.g., width/min-width/max-width)
// - Create ONE shared evaluator with parameterized keywords
// - Use type aliases to point to the shared evaluator
// - Example: width, min-width, max-width all use CSSLengthValue | CSSPercentageValue | [Keywords]
// - This eliminates duplicate code and ensures consistent behavior
// =============================================================================
// CENTRALIZED KEYWORD ARRAYS
// =============================================================================
// Keyword arrays moved from individual evaluators for centralization and reuse
// Font Keywords
export const FONT_STYLE_KEYWORDS = ['normal', 'italic', 'oblique'];
export const FONT_VARIANT_KEYWORDS = ['normal', 'small-caps'];
export const FONT_WEIGHT_KEYWORDS = ['normal', 'bold', 'bolder', 'lighter'];
export const FONT_STRETCH_KEYWORDS = [
'normal', 'ultra-condensed', 'extra-condensed', 'condensed', 'semi-condensed',
'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded'
];
export const FONT_SIZE_KEYWORDS = [
'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', 'xxx-large',
'larger', 'smaller', 'math'
];
export const SYSTEM_FONT_KEYWORDS = ['caption', 'icon', 'menu', 'message-box', 'small-caption', 'status-bar'];
// Text Keywords
export const TEXT_ALIGN_KEYWORDS = [
'left', 'right', 'center', 'justify', 'justify-all', 'start', 'end', 'match-parent'
];
export const TEXT_TRANSFORM_KEYWORDS = [
'none', 'capitalize', 'uppercase', 'lowercase', 'full-width', 'full-size-kana'
];
export const TEXT_DECORATION_LINE_KEYWORDS = ['none', 'underline', 'overline', 'line-through', 'blink'];
export const TEXT_DECORATION_STYLE_KEYWORDS = ['solid', 'double', 'dotted', 'dashed', 'wavy'];
export const TEXT_DECORATION_THICKNESS_KEYWORDS = ['auto', 'from-font', 'thin', 'medium', 'thick'];
export const LETTER_SPACING_KEYWORDS = ['normal'];
export const TEXT_OVERFLOW_KEYWORDS = ['clip', 'ellipsis'];
export const OBJECT_FIT_KEYWORDS = ['fill', 'contain', 'cover', 'none', 'scale-down'];
export const TEXT_INDENT_KEYWORDS = ['each-line', 'hanging'];
export const WHITE_SPACE_KEYWORDS = ['normal', 'nowrap', 'pre', 'pre-wrap', 'pre-line', 'break-spaces'];
export const WORD_BREAK_KEYWORDS = ['normal', 'break-all', 'keep-all', 'break-word'];
export const OVERFLOW_WRAP_KEYWORDS = ['normal', 'anywhere', 'break-word'];
export const WRITING_MODE_KEYWORDS = ['horizontal-tb', 'vertical-rl', 'vertical-lr'];
// Blend Mode Keywords
export const BLEND_MODE_KEYWORDS = [
'normal',
'multiply',
'screen',
'overlay',
'darken',
'lighten',
'color-dodge',
'color-burn',
'hard-light',
'soft-light',
'difference',
'exclusion',
'hue',
'saturation',
'color',
'luminosity'
];
// Box Model Keywords
export const BOX_KEYWORDS = ['border-box', 'padding-box', 'content-box'];
// Background Keywords
export const BACKGROUND_ATTACHMENT_KEYWORDS = ['scroll', 'fixed', 'local'];
export const BACKGROUND_REPEAT_KEYWORDS = ['repeat', 'no-repeat', 'repeat-x', 'repeat-y', 'space', 'round'];
export const BACKGROUND_SIZE_KEYWORDS = ['auto', 'cover', 'contain'];
export const BACKGROUND_COLOR_KEYWORDS = ['transparent'];
export const BACKGROUND_IMAGE_KEYWORDS = ['none'];
// Border Keywords
export const BORDER_STYLE_KEYWORDS = [
'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'
];
export const BORDER_WIDTH_KEYWORDS = ['thin', 'medium', 'thick'];
// Flexbox Keywords
export const FLEX_DIRECTION_KEYWORDS = ['row', 'row-reverse', 'column', 'column-reverse'];
// Alignment Keywords
export const BASIC_ALIGNMENT_KEYWORDS = ['normal', 'stretch'];
export const BASIC_ALIGNMENT_WITH_AUTO_KEYWORDS = ['auto', 'normal', 'stretch'];
export const POSITIONAL_ALIGNMENT_KEYWORDS = [
'center', 'start', 'end', 'self-start', 'self-end', 'flex-start', 'flex-end', 'left', 'right', 'anchor-center'
];
export const BASELINE_ALIGNMENT_KEYWORDS = ['baseline', 'first baseline', 'last baseline'];
export const OVERFLOW_ALIGNMENT_KEYWORDS = ['safe', 'unsafe'];
// Sizing Keywords (used by width, height, min-width, min-height, max-width, max-height)
export const SIZING_KEYWORDS = [
'max-content', // Intrinsic preferred size
'min-content', // Intrinsic minimum size
'fit-content', // fit-content() function
'fill-available', // Legacy webkit property
'available' // Available space
];
export const AUTO_KEYWORD = 'auto';
export const NONE_KEYWORD = 'none';
// Combined keywords for different property types
export const BASIC_SIZING_KEYWORDS = [
AUTO_KEYWORD,
...SIZING_KEYWORDS
];
export const MAX_SIZING_KEYWORDS = [
NONE_KEYWORD,
...SIZING_KEYWORDS
];
// Justify Content Keywords
export const JUSTIFY_CONTENT_NORMAL_KEYWORDS = ['normal'];
export const JUSTIFY_CONTENT_DISTRIBUTED_KEYWORDS = ['space-between', 'space-around', 'space-evenly', 'stretch'];
// Display Keywords
export const DISPLAY_KEYWORDS = [
// Basic display values
'block', 'inline', 'inline-block',
// Flexbox display values
'flex', 'inline-flex',
// Grid display values
'grid', 'inline-grid',
// Table display values
'table', 'inline-table', 'table-row', 'table-column', 'table-row-group',
'table-column-group', 'table-header-group', 'table-footer-group',
'table-cell', 'table-caption',
// List display values
'list-item',
// Other display values
'none', 'contents',
// Flow-root (modern block formatting context)
'flow-root',
// Ruby display values (for Asian typography)
'ruby', 'ruby-base', 'ruby-text', 'ruby-base-container', 'ruby-text-container'
];
// Overflow Keywords
export const OVERFLOW_KEYWORDS = [
'visible', // Default - content not clipped, may overflow
'hidden', // Content is clipped, no scrollbars
'scroll', // Content is clipped, scrollbars always shown
'auto', // Content is clipped, scrollbars shown when needed
'clip' // Content is clipped, no scrolling mechanism (newer value)
];
// Visibility Keywords
export const VISIBILITY_KEYWORDS = [
'visible', // Default - element is visible
'hidden', // Element is invisible but takes up space
'collapse' // Element is removed from layout (mainly for table elements)
];
// Z-Index Keywords
export const Z_INDEX_KEYWORDS = [
'auto' // Default - stack level equals parent element
];
export const ANCHOR_SIZE_KEYWORDS = ['width', 'height', 'block', 'inline', 'self-block', 'self-inline'];
// =============================================================================
// CSS GRID LAYOUT TYPES
// =============================================================================
/**
* CSS Grid Track Sizing Keywords - MDN specification
* https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns
*/
export const GRID_TRACK_SIZING_KEYWORDS = ['auto', 'max-content', 'min-content'];
/**
* CSS Grid Template Keywords
*/
export const GRID_TEMPLATE_KEYWORDS = ['none', 'subgrid', 'masonry'];
/**
* CSS Grid Column Keywords (for shorthand property)
*/
export const GRID_COLUMN_KEYWORDS = ['auto'];
/**
* CSS Grid Row Keywords (for shorthand property)
*/
export const GRID_ROW_KEYWORDS = ['auto'];
// =============================================================================
// LEGACY COMPATIBILITY TYPES
// =============================================================================
// No legacy types needed - all types are now centralized
// =============================================================================
// SHARED EVALUATOR GROUPS - DOCUMENTATION
// =============================================================================
//
// SIZING PROPERTIES GROUP - Same Root Type Pattern
// Root: CSSLengthValue | CSSPercentageValue | [PropertyKeywords]
// Shared Logic: All use identical parsing (length/percentage + non-negative validation)
// Difference: Only keyword arrays differ (BASIC_SIZING vs MAX_SIZING)
// Properties: HeightValue, WidthValue, MaxHeightValue, MaxWidthValue, MinHeightValue, MinWidthValue
//
// GAP PROPERTIES GROUP - Same Root Type Pattern
// Root: CSSLengthValue | CSSPercentageValue | [NormalKeyword]
// Shared Logic: All use identical parsing (length/percentage + non-negative validation)
// Properties: ColumnGapValue, RowGapValue
//
// SIMPLE PROPERTIES - Unique Evaluators
// Properties: OpacityValue, LetterSpacingValue, etc.