Skip to content

Commit

Permalink
Enable Flex declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
goanpeca committed Apr 27, 2020
1 parent 61880b7 commit f36f298
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 18 deletions.
36 changes: 19 additions & 17 deletions colosseum/declaration.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from . import engine as css_engine
from . import parser
from . import engine as css_engine, parser
from .constants import ( # noqa
ALIGN_CONTENT_CHOICES, ALIGN_ITEMS_CHOICES, ALIGN_SELF_CHOICES, AUTO,
BACKGROUND_COLOR_CHOICES, BORDER_COLLAPSE_CHOICES, BORDER_COLOR_CHOICES,
Expand All @@ -15,16 +14,19 @@
NOWRAP, ORDER_CHOICES, ORPHANS_CHOICES, OUTLINE_COLOR_CHOICES,
OUTLINE_STYLE_CHOICES, OUTLINE_WIDTH_CHOICES, OVERFLOW_CHOICES,
PADDING_CHOICES, PAGE_BREAK_AFTER_CHOICES, PAGE_BREAK_BEFORE_CHOICES,
PAGE_BREAK_INSIDE_CHOICES, POSITION_CHOICES, QUOTES_CHOICES, ROW,
SEPARATE, SHOW, SIZE_CHOICES, STATIC, STRETCH, TABLE_LAYOUT_CHOICES,
PAGE_BREAK_INSIDE_CHOICES, POSITION_CHOICES, QUOTES_CHOICES, ROW, SEPARATE,
SHOW, SIZE_CHOICES, STATIC, STRETCH, TABLE_LAYOUT_CHOICES,
TEXT_ALIGN_CHOICES, TEXT_DECORATION_CHOICES, TEXT_INDENT_CHOICES,
TEXT_TRANSFORM_CHOICES, TOP, TRANSPARENT, UNICODE_BIDI_CHOICES,
VISIBILITY_CHOICES, VISIBLE, WHITE_SPACE_CHOICES, WIDOWS_CHOICES,
WORD_SPACING_CHOICES, Z_INDEX_CHOICES, OtherProperty,
TextAlignInitialValue, default, CURSOR_CHOICES,
)
from .exceptions import ValidationError
from .wrappers import Border, BorderBottom, BorderLeft, BorderRight, BorderTop, Outline
from .wrappers import ( # noqa
Border, BorderBottom, BorderLeft, BorderRight, BorderTop, Flex, FlexFlow,
Outline
)

_CSS_PROPERTIES = set()

Expand Down Expand Up @@ -424,36 +426,36 @@ def __init__(self, **style):

# 5. Ordering and orientation ########################################
# 5.1 Flex flow direction
# flex_direction = validated_property('flex_direction', choices=FLEX_DIRECTION_CHOICES, initial=ROW)
flex_direction = validated_property('flex_direction', choices=FLEX_DIRECTION_CHOICES, initial=ROW)

# 5.2 Flex line wrapping
# flex_wrap = validated_property('flex_wrap', choices=FLEX_WRAP_CHOICES, initial=NOWRAP)
flex_wrap = validated_property('flex_wrap', choices=FLEX_WRAP_CHOICES, initial=NOWRAP)

# 5.3 Flex direction and wrap
# flex_flow =
flex_flow = validated_shorthand_property('flex_flow', parser=parser.flex_flow, wrapper=FlexFlow)

# 5.4 Display order
# order = validated_property('order', choices=ORDER_CHOICES, initial=0)
order = validated_property('order', choices=ORDER_CHOICES, initial=0)

# 7. Flexibility #####################################################
# 7.2 Components of flexibility
# flex_grow = validated_property('flex_grow', choices=FLEX_GROW_CHOICES, initial=0)
# flex_shrink = validated_property('flex_shrink', choices=FLEX_SHRINK_CHOICES, initial=1)
# flex_basis = validated_property('flex_basis', choices=FLEX_BASIS_CHOICES, initial=AUTO)
flex_grow = validated_property('flex_grow', choices=FLEX_GROW_CHOICES, initial=0)
flex_shrink = validated_property('flex_shrink', choices=FLEX_SHRINK_CHOICES, initial=1)
flex_basis = validated_property('flex_basis', choices=FLEX_BASIS_CHOICES, initial=AUTO)

# 7.1 The 'flex' shorthand
# flex =
flex = validated_shorthand_property('flex', parser=parser.flex, wrapper=Flex)

# 8. Alignment #######################################################
# 8.2 Axis alignment
# justify_content = validated_property('justify_content', choices=JUSTIFY_CONTENT_CHOICES, initial=FLEX_START)
justify_content = validated_property('justify_content', choices=JUSTIFY_CONTENT_CHOICES, initial=FLEX_START)

# 8.3 Cros-axis alignment
# align_items = validated_property('align_items', choices=ALIGN_ITEMS_CHOICES, initial=STRETCH)
# align_self = validated_property('align_self', choices=ALIGN_SELF_CHOICES, initial=AUTO)
align_items = validated_property('align_items', choices=ALIGN_ITEMS_CHOICES, initial=STRETCH)
align_self = validated_property('align_self', choices=ALIGN_SELF_CHOICES, initial=AUTO)

# 8.4 Packing flex lines
# align_content = validated_property('align_content', choices=ALIGN_CONTENT_CHOICES, initial=STRETCH)
align_content = validated_property('align_content', choices=ALIGN_CONTENT_CHOICES, initial=STRETCH)

######################################################################
# Grid properties
Expand Down
125 changes: 125 additions & 0 deletions colosseum/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,3 +445,128 @@ def cursor(values):
raise ValueError('Value {value} is not a valid cursor value'.format(value=value))

return Cursor(validated_values)


##############################################################################
# Flex Flow
##############################################################################
def _parse_flex_flow_property_part(value, flex_flow_dict):
"""Parse flex_flow shorthand property part for known properties."""
from .constants import FLEX_DIRECTION_CHOICES, FLEX_WRAP_CHOICES

property_validators = {
'flex_direction': FLEX_DIRECTION_CHOICES,
'flex_wrap': FLEX_WRAP_CHOICES,
}

for property_name, choices in property_validators.items():
try:
value = choices.validate(value)
except (ValueError, ValidationError):
continue

if property_name in flex_flow_dict:
raise ValueError('Invalid duplicated property!')

flex_flow_dict[property_name] = value
return flex_flow_dict

raise ValueError('Flex flow value "{value}" not valid!'.format(value=value))


def flex_flow(value):
"""
Parse flex flow string into a dictionary of properties.
The font CSS property is a shorthand for flex-wrap and flex-direction.
Reference:
- https://www.w3.org/TR/css-flexbox-1/#flex-flow-property
"""
if value:
if isinstance(value, str):
values = [val.strip() for val in value.split()]
elif isinstance(value, Sequence):
values = value
else:
raise ValueError('Unknown flex flow %s ' % value)
else:
raise ValueError('Unknown flex flow %s ' % value)

# We iteratively split by the first left hand space found and try to validate if that part
# is a valid <flex-wrap> or <flex-direction> (which can come in any order)

# We use this dictionary to store parsed values and check that values properties are not
# duplicated
flex_flow_dict = {}
for idx, part in enumerate(values):
if idx > 1:
# Flex flow can have a maximum of 2 parts
raise ValueError('Flex flow property shorthand contains too many parts!')

flex_flow_dict = _parse_flex_flow_property_part(part, flex_flow_dict)

return flex_flow_dict


##############################################################################
# Flex
##############################################################################
def _parse_flex_property_part(value, flex_dict):
"""Parse flex shorthand property part for known properties."""
from .constants import FLEX_GROW_CHOICES, FLEX_SHRINK_CHOICES, FLEX_BASIS_CHOICES

property_validators = {
'flex_grow': FLEX_GROW_CHOICES,
'flex_shrink': FLEX_SHRINK_CHOICES,
'flex_basis': FLEX_BASIS_CHOICES,
}

for property_name, choices in property_validators.items():
try:
value = choices.validate(value)
except (ValueError, ValidationError):
continue

if property_name in flex_dict:
raise ValueError('Invalid duplicated property!')

flex_dict[property_name] = value
return flex_dict

raise ValueError('Flex value "{value}" not valid!'.format(value=value))


def flex(value):
"""
Parse flex string into a dictionary of properties.
The font CSS property is a shorthand for flex-grow, flex-shrink and flex-basis.
Reference:
- https://www.w3.org/TR/css-flexbox-1/#flex-property
"""
if value:
if isinstance(value, str):
values = [val.strip() for val in value.split()]
elif isinstance(value, Sequence):
values = value
else:
raise ValueError('Unknown flex %s ' % value)
else:
raise ValueError('Unknown flex %s ' % value)

# We iteratively split by the first left hand space found and try to validate if that part
# is a valid <flex-grow> or <flex-shrink> or <flex-basis> (which can come in any order)

# We use this dictionary to store parsed values and check that values properties are not
# duplicated
flex_dict = {}
for idx, part in enumerate(values):
if idx > 2:
# Flex can have a maximum of 3 parts
raise ValueError('Flex property shorthand contains too many parts!')

flex_dict = _parse_flex_property_part(part, flex_dict)

return flex_dict
13 changes: 12 additions & 1 deletion colosseum/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def __repr__(self):

def __str__(self):
parts = []
for key, value in self.to_dict().items():
for __, value in self.to_dict().items():
parts.append(str(value))

return ' '.join(parts)
Expand Down Expand Up @@ -235,3 +235,14 @@ def sort(self, cmp=None, key=None, reverse=False):

class Cursor(ImmutableList):
"""Immutable list to store cursor property."""


##############################################################################
# Flex
##############################################################################
class FlexFlow(Shorthand):
VALID_KEYS = ['flex_direction', 'flex_wrap']


class Flex(Shorthand):
VALID_KEYS = ['flex_grow', 'flex_shrink', 'flex_basis']

0 comments on commit f36f298

Please sign in to comment.