├── .gitignore ├── .vscode └── launch.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Programming Rust 2nd.md ├── README.md ├── components ├── common │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── url.rs │ │ └── vector.rs ├── css │ ├── Cargo.toml │ ├── src │ │ ├── computed_values.rs │ │ ├── css_writer.rs │ │ ├── element_state.rs │ │ ├── error_reporting.rs │ │ ├── lib.rs │ │ ├── media_queries │ │ │ ├── media_condition.rs │ │ │ ├── media_feature_expression.rs │ │ │ ├── media_features.rs │ │ │ ├── media_list.rs │ │ │ ├── media_query.rs │ │ │ └── mod.rs │ │ ├── parser.rs │ │ ├── properties │ │ │ ├── custom_properties.rs │ │ │ ├── declaration.rs │ │ │ ├── declaration_block.rs │ │ │ ├── longhand_id.rs │ │ │ ├── longhands │ │ │ │ ├── align_content.rs │ │ │ │ ├── align_items.rs │ │ │ │ ├── align_self.rs │ │ │ │ ├── animation_delay.rs │ │ │ │ ├── animation_direction.rs │ │ │ │ ├── animation_duration.rs │ │ │ │ ├── animation_fill_mode.rs │ │ │ │ ├── animation_iteration_count.rs │ │ │ │ ├── animation_name.rs │ │ │ │ ├── animation_play_state.rs │ │ │ │ ├── animation_timing_function.rs │ │ │ │ ├── aspect_ratio.rs │ │ │ │ ├── backface_visibility.rs │ │ │ │ ├── background_attachment.rs │ │ │ │ ├── background_clip.rs │ │ │ │ ├── background_color.rs │ │ │ │ ├── background_image.rs │ │ │ │ ├── background_origin.rs │ │ │ │ ├── background_position_x.rs │ │ │ │ ├── background_position_y.rs │ │ │ │ ├── background_repeat.rs │ │ │ │ ├── background_size.rs │ │ │ │ ├── block_size.rs │ │ │ │ ├── border_block_end_color.rs │ │ │ │ ├── border_block_end_style.rs │ │ │ │ ├── border_block_end_width.rs │ │ │ │ ├── border_block_start_color.rs │ │ │ │ ├── border_block_start_style.rs │ │ │ │ ├── border_block_start_width.rs │ │ │ │ ├── border_bottom_color.rs │ │ │ │ ├── border_bottom_left_radius.rs │ │ │ │ ├── border_bottom_right_radius.rs │ │ │ │ ├── border_bottom_style.rs │ │ │ │ ├── border_bottom_width.rs │ │ │ │ ├── border_collapse.rs │ │ │ │ ├── border_end_end_radius.rs │ │ │ │ ├── border_end_start_radius.rs │ │ │ │ ├── border_image_outset.rs │ │ │ │ ├── border_image_repeat.rs │ │ │ │ ├── border_image_slice.rs │ │ │ │ ├── border_image_source.rs │ │ │ │ ├── border_image_width.rs │ │ │ │ ├── border_inline_end_color.rs │ │ │ │ ├── border_inline_end_style.rs │ │ │ │ ├── border_inline_end_width.rs │ │ │ │ ├── border_inline_start_color.rs │ │ │ │ ├── border_inline_start_style.rs │ │ │ │ ├── border_inline_start_width.rs │ │ │ │ ├── border_left_color.rs │ │ │ │ ├── border_left_style.rs │ │ │ │ ├── border_left_width.rs │ │ │ │ ├── border_right_color.rs │ │ │ │ ├── border_right_style.rs │ │ │ │ ├── border_right_width.rs │ │ │ │ ├── border_spacing.rs │ │ │ │ ├── border_start_end_radius.rs │ │ │ │ ├── border_start_start_radius.rs │ │ │ │ ├── border_top_color.rs │ │ │ │ ├── border_top_left_radius.rs │ │ │ │ ├── border_top_right_radius.rs │ │ │ │ ├── border_top_style.rs │ │ │ │ ├── border_top_width.rs │ │ │ │ ├── bottom.rs │ │ │ │ ├── box_shadow.rs │ │ │ │ ├── box_sizing.rs │ │ │ │ ├── caption_side.rs │ │ │ │ ├── clear.rs │ │ │ │ ├── clip.rs │ │ │ │ ├── color.rs │ │ │ │ ├── column_count.rs │ │ │ │ ├── column_gap.rs │ │ │ │ ├── column_width.rs │ │ │ │ ├── content.rs │ │ │ │ ├── counter_increment.rs │ │ │ │ ├── counter_reset.rs │ │ │ │ ├── counter_set.rs │ │ │ │ ├── cursor.rs │ │ │ │ ├── direction.rs │ │ │ │ ├── display.rs │ │ │ │ ├── empty_cells.rs │ │ │ │ ├── filter.rs │ │ │ │ ├── flex_basis.rs │ │ │ │ ├── flex_direction.rs │ │ │ │ ├── flex_grow.rs │ │ │ │ ├── flex_shrink.rs │ │ │ │ ├── flex_wrap.rs │ │ │ │ ├── float.rs │ │ │ │ ├── font_family.rs │ │ │ │ ├── font_size.rs │ │ │ │ ├── font_stretch.rs │ │ │ │ ├── font_style.rs │ │ │ │ ├── font_variant_caps.rs │ │ │ │ ├── font_weight.rs │ │ │ │ ├── height.rs │ │ │ │ ├── image_rendering.rs │ │ │ │ ├── inline_size.rs │ │ │ │ ├── inset_block_end.rs │ │ │ │ ├── inset_block_start.rs │ │ │ │ ├── inset_inline_end.rs │ │ │ │ ├── inset_inline_start.rs │ │ │ │ ├── justify_content.rs │ │ │ │ ├── left.rs │ │ │ │ ├── letter_spacing.rs │ │ │ │ ├── line_height.rs │ │ │ │ ├── list_style_image.rs │ │ │ │ ├── list_style_position.rs │ │ │ │ ├── list_style_type.rs │ │ │ │ ├── margin_block_end.rs │ │ │ │ ├── margin_block_start.rs │ │ │ │ ├── margin_bottom.rs │ │ │ │ ├── margin_inline_end.rs │ │ │ │ ├── margin_inline_start.rs │ │ │ │ ├── margin_left.rs │ │ │ │ ├── margin_right.rs │ │ │ │ ├── margin_top.rs │ │ │ │ ├── max_block_size.rs │ │ │ │ ├── max_height.rs │ │ │ │ ├── max_inline_size.rs │ │ │ │ ├── max_width.rs │ │ │ │ ├── min_block_size.rs │ │ │ │ ├── min_height.rs │ │ │ │ ├── min_inline_size.rs │ │ │ │ ├── min_width.rs │ │ │ │ ├── mix_blend_mode.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── object_fit.rs │ │ │ │ ├── opacity.rs │ │ │ │ ├── order.rs │ │ │ │ ├── outline_color.rs │ │ │ │ ├── outline_offset.rs │ │ │ │ ├── outline_style.rs │ │ │ │ ├── outline_width.rs │ │ │ │ ├── overflow_block.rs │ │ │ │ ├── overflow_inline.rs │ │ │ │ ├── overflow_wrap.rs │ │ │ │ ├── overflow_x.rs │ │ │ │ ├── overflow_y.rs │ │ │ │ ├── padding_block_end.rs │ │ │ │ ├── padding_block_start.rs │ │ │ │ ├── padding_bottom.rs │ │ │ │ ├── padding_inline_end.rs │ │ │ │ ├── padding_inline_start.rs │ │ │ │ ├── padding_left.rs │ │ │ │ ├── padding_right.rs │ │ │ │ ├── padding_top.rs │ │ │ │ ├── perspective.rs │ │ │ │ ├── perspective_origin.rs │ │ │ │ ├── pointer_events.rs │ │ │ │ ├── position.rs │ │ │ │ ├── quotes.rs │ │ │ │ ├── right.rs │ │ │ │ ├── rotate.rs │ │ │ │ ├── scale.rs │ │ │ │ ├── table_layout.rs │ │ │ │ ├── text_align.rs │ │ │ │ ├── text_decoration_line.rs │ │ │ │ ├── text_indent.rs │ │ │ │ ├── text_justify.rs │ │ │ │ ├── text_overflow.rs │ │ │ │ ├── text_rendering.rs │ │ │ │ ├── text_shadow.rs │ │ │ │ ├── text_transform.rs │ │ │ │ ├── top.rs │ │ │ │ ├── transform.rs │ │ │ │ ├── transform_origin.rs │ │ │ │ ├── transform_style.rs │ │ │ │ ├── transition_delay.rs │ │ │ │ ├── transition_duration.rs │ │ │ │ ├── transition_property.rs │ │ │ │ ├── transition_timing_function.rs │ │ │ │ ├── translate.rs │ │ │ │ ├── unicode_bidi.rs │ │ │ │ ├── vertical_align.rs │ │ │ │ ├── visibility.rs │ │ │ │ ├── white_space.rs │ │ │ │ ├── width.rs │ │ │ │ ├── word_break.rs │ │ │ │ ├── word_spacing.rs │ │ │ │ ├── writing_mode.rs │ │ │ │ └── z_index.rs │ │ │ ├── mod.rs │ │ │ ├── property_id.rs │ │ │ ├── shorthand_id.rs │ │ │ └── shorthands │ │ │ │ ├── animation.rs │ │ │ │ ├── background.rs │ │ │ │ ├── background_position.rs │ │ │ │ ├── border.rs │ │ │ │ ├── border_block.rs │ │ │ │ ├── border_block_color.rs │ │ │ │ ├── border_block_end.rs │ │ │ │ ├── border_block_start.rs │ │ │ │ ├── border_block_style.rs │ │ │ │ ├── border_block_width.rs │ │ │ │ ├── border_bottom.rs │ │ │ │ ├── border_color.rs │ │ │ │ ├── border_image.rs │ │ │ │ ├── border_inline.rs │ │ │ │ ├── border_inline_color.rs │ │ │ │ ├── border_inline_end.rs │ │ │ │ ├── border_inline_start.rs │ │ │ │ ├── border_inline_style.rs │ │ │ │ ├── border_inline_width.rs │ │ │ │ ├── border_left.rs │ │ │ │ ├── border_radius.rs │ │ │ │ ├── border_right.rs │ │ │ │ ├── border_style.rs │ │ │ │ ├── border_top.rs │ │ │ │ ├── border_width.rs │ │ │ │ ├── columns.rs │ │ │ │ ├── flex.rs │ │ │ │ ├── flex_flow.rs │ │ │ │ ├── font.rs │ │ │ │ ├── font_variant.rs │ │ │ │ ├── inset.rs │ │ │ │ ├── inset_block.rs │ │ │ │ ├── inset_inline.rs │ │ │ │ ├── list_style.rs │ │ │ │ ├── margin.rs │ │ │ │ ├── margin_block.rs │ │ │ │ ├── margin_inline.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── outline.rs │ │ │ │ ├── overflow.rs │ │ │ │ ├── padding.rs │ │ │ │ ├── padding_block.rs │ │ │ │ ├── padding_inline.rs │ │ │ │ ├── text_decoration.rs │ │ │ │ └── transition.rs │ │ ├── selectors │ │ │ ├── mod.rs │ │ │ ├── nonts_pseudo_class.rs │ │ │ ├── pseudo_element.rs │ │ │ ├── select.rs │ │ │ └── selector_parser.rs │ │ ├── str.rs │ │ ├── stylesheets │ │ │ ├── css_rule.rs │ │ │ ├── keyframe_rule.rs │ │ │ ├── media_rule.rs │ │ │ ├── mod.rs │ │ │ ├── namespace_rule.rs │ │ │ ├── origin.rs │ │ │ ├── page_rule.rs │ │ │ ├── rule_parser.rs │ │ │ ├── style_rule.rs │ │ │ ├── stylesheet.rs │ │ │ └── support_rule.rs │ │ ├── stylist.rs │ │ └── values │ │ │ ├── animation.rs │ │ │ ├── computed │ │ │ ├── length.rs │ │ │ ├── line.rs │ │ │ └── mod.rs │ │ │ ├── generics │ │ │ ├── border.rs │ │ │ ├── counter.rs │ │ │ ├── length.rs │ │ │ ├── mod.rs │ │ │ └── number.rs │ │ │ ├── mod.rs │ │ │ ├── specified │ │ │ ├── angle.rs │ │ │ ├── border.rs │ │ │ ├── color.rs │ │ │ ├── counter.rs │ │ │ ├── easing.rs │ │ │ ├── image.rs │ │ │ ├── layout.rs │ │ │ ├── leader.rs │ │ │ ├── length.rs │ │ │ ├── line.rs │ │ │ ├── mod.rs │ │ │ ├── number.rs │ │ │ ├── percentage.rs │ │ │ ├── position.rs │ │ │ ├── quote.rs │ │ │ ├── target.rs │ │ │ ├── time.rs │ │ │ └── transform.rs │ │ │ └── url.rs │ └── tests │ │ ├── keyframes.rs │ │ ├── media.rs │ │ ├── namespace.rs │ │ ├── page.rs │ │ ├── properties.rs │ │ ├── properties │ │ ├── align_content.rs │ │ ├── align_items.rs │ │ ├── align_self.rs │ │ ├── animation_delay.rs │ │ ├── animation_direction.rs │ │ ├── animation_duration.rs │ │ ├── animation_fill_mode.rs │ │ ├── animation_iteration_count.rs │ │ ├── animation_name.rs │ │ ├── animation_play_state.rs │ │ ├── animation_timing_function.rs │ │ ├── aspect_ratio.rs │ │ ├── backface_visibility.rs │ │ ├── background_attachment.rs │ │ ├── background_clip.rs │ │ ├── background_color.rs │ │ ├── background_image.rs │ │ ├── background_origin.rs │ │ ├── background_position_x.rs │ │ ├── background_position_y.rs │ │ ├── background_repeat.rs │ │ ├── background_size.rs │ │ ├── block_size.rs │ │ ├── border_block_end_color.rs │ │ ├── border_block_end_style.rs │ │ ├── border_block_end_width.rs │ │ ├── border_block_start_color.rs │ │ ├── border_block_start_style.rs │ │ ├── border_block_start_width.rs │ │ ├── border_bottom_color.rs │ │ ├── border_bottom_left_radius.rs │ │ ├── border_bottom_right_radius.rs │ │ ├── border_bottom_style.rs │ │ ├── border_bottom_width.rs │ │ ├── border_collapse.rs │ │ ├── border_end_end_radius.rs │ │ ├── border_end_start_radius.rs │ │ ├── border_image_outset.rs │ │ ├── border_image_repeat.rs │ │ ├── border_image_slice.rs │ │ ├── border_image_source.rs │ │ ├── border_image_width.rs │ │ ├── border_inline_end_color.rs │ │ ├── border_inline_end_style.rs │ │ ├── border_inline_end_width.rs │ │ ├── border_inline_start_color.rs │ │ ├── border_inline_start_style.rs │ │ ├── border_inline_start_width.rs │ │ ├── border_left_color.rs │ │ ├── border_left_style.rs │ │ ├── border_left_width.rs │ │ ├── border_right_color.rs │ │ ├── border_right_style.rs │ │ ├── border_right_width.rs │ │ ├── border_spacing.rs │ │ ├── border_start_end_radius.rs │ │ ├── border_start_start_radius.rs │ │ ├── border_top_color.rs │ │ ├── border_top_left_radius.rs │ │ ├── border_top_right_radius.rs │ │ ├── border_top_style.rs │ │ ├── border_top_width.rs │ │ ├── bottom.rs │ │ ├── box_shadow.rs │ │ ├── box_sizing.rs │ │ ├── caption_side.rs │ │ ├── clear.rs │ │ ├── clip.rs │ │ ├── color.rs │ │ ├── column_count.rs │ │ ├── column_gap.rs │ │ ├── column_width.rs │ │ ├── content.rs │ │ ├── counter_increment.rs │ │ ├── counter_reset.rs │ │ ├── counter_set.rs │ │ ├── cursor.rs │ │ ├── direction.rs │ │ ├── display.rs │ │ ├── empty_cells.rs │ │ ├── filter.rs │ │ ├── flex_basis.rs │ │ ├── flex_direction.rs │ │ ├── flex_grow.rs │ │ ├── flex_shrink.rs │ │ ├── flex_wrap.rs │ │ ├── float.rs │ │ ├── font_family.rs │ │ ├── font_size.rs │ │ ├── font_stretch.rs │ │ ├── font_style.rs │ │ ├── font_variant_caps.rs │ │ ├── font_weight.rs │ │ ├── height.rs │ │ ├── image_rendering.rs │ │ ├── inline_size.rs │ │ ├── inset_block_end.rs │ │ ├── inset_block_start.rs │ │ ├── inset_inline_end.rs │ │ ├── inset_inline_start.rs │ │ ├── justify_content.rs │ │ ├── left.rs │ │ ├── letter_spacing.rs │ │ ├── line_height.rs │ │ ├── list_style_image.rs │ │ ├── list_style_position.rs │ │ ├── list_style_type.rs │ │ ├── margin_block_end.rs │ │ ├── margin_block_start.rs │ │ ├── margin_bottom.rs │ │ ├── margin_inline_end.rs │ │ ├── margin_inline_start.rs │ │ ├── margin_left.rs │ │ ├── margin_right.rs │ │ ├── margin_top.rs │ │ ├── max_block_size.rs │ │ ├── max_height.rs │ │ ├── max_inline_size.rs │ │ ├── max_width.rs │ │ ├── min_block_size.rs │ │ ├── min_height.rs │ │ ├── min_inline_size.rs │ │ ├── min_width.rs │ │ ├── mix_blend_mode.rs │ │ ├── object_fit.rs │ │ ├── opacity.rs │ │ ├── order.rs │ │ ├── outline_color.rs │ │ ├── outline_offset.rs │ │ ├── outline_style.rs │ │ ├── outline_width.rs │ │ ├── overflow_block.rs │ │ ├── overflow_inline.rs │ │ ├── overflow_wrap.rs │ │ ├── overflow_x.rs │ │ ├── overflow_y.rs │ │ ├── padding_block_end.rs │ │ ├── padding_block_start.rs │ │ ├── padding_bottom.rs │ │ ├── padding_inline_end.rs │ │ ├── padding_inline_start.rs │ │ ├── padding_left.rs │ │ ├── padding_right.rs │ │ ├── padding_top.rs │ │ ├── perspective.rs │ │ ├── perspective_origin.rs │ │ ├── pointer_events.rs │ │ ├── position.rs │ │ ├── quotes.rs │ │ ├── right.rs │ │ ├── rotate.rs │ │ ├── scale.rs │ │ ├── table_layout.rs │ │ ├── text_align.rs │ │ ├── text_decoration_line.rs │ │ ├── text_indent.rs │ │ ├── text_justify.rs │ │ ├── text_overflow.rs │ │ ├── text_rendering.rs │ │ ├── text_shadow.rs │ │ ├── text_transform.rs │ │ ├── top.rs │ │ ├── transform.rs │ │ ├── transform_origin.rs │ │ ├── transform_style.rs │ │ ├── transition_delay.rs │ │ ├── transition_duration.rs │ │ ├── transition_property.rs │ │ ├── transition_timing_function.rs │ │ ├── translate.rs │ │ ├── unicode_bidi.rs │ │ ├── vertical_align.rs │ │ ├── visibility.rs │ │ ├── white_space.rs │ │ ├── width.rs │ │ ├── word_break.rs │ │ ├── word_spacing.rs │ │ ├── writing_mode.rs │ │ └── z_index.rs │ │ ├── setup │ │ └── mod.rs │ │ ├── shorthands.rs │ │ ├── shorthands │ │ ├── border_color.rs │ │ ├── border_style.rs │ │ ├── border_width.rs │ │ ├── margin.rs │ │ ├── margin_block.rs │ │ ├── margin_inline.rs │ │ ├── padding.rs │ │ ├── padding_block.rs │ │ └── padding_inline.rs │ │ ├── supports.rs │ │ ├── values.rs │ │ └── values │ │ ├── angle.rs │ │ ├── animation.rs │ │ ├── border.rs │ │ ├── color.rs │ │ ├── content.rs │ │ ├── counter.rs │ │ ├── easing.rs │ │ ├── filter.rs │ │ ├── image.rs │ │ ├── layout.rs │ │ ├── length.rs │ │ ├── line.rs │ │ ├── number.rs │ │ ├── percentage.rs │ │ ├── position.rs │ │ ├── time.rs │ │ ├── transform.rs │ │ └── url.rs ├── dom │ ├── Cargo.toml │ ├── README.md │ ├── servo.drawio │ ├── src │ │ ├── attr.rs │ │ ├── cdatasection.rs │ │ ├── characterdata.rs │ │ ├── comment.rs │ │ ├── customelementregistry.rs │ │ ├── document.rs │ │ ├── documentfragment.rs │ │ ├── documenttype.rs │ │ ├── element.rs │ │ ├── error.rs │ │ ├── global_scope.rs │ │ ├── htmlbaseelement.rs │ │ ├── htmlbodyelement.rs │ │ ├── htmldivelement.rs │ │ ├── htmlelement.rs │ │ ├── htmlheadelement.rs │ │ ├── htmlheadingelement.rs │ │ ├── htmlhtmlelement.rs │ │ ├── htmlparagraphelement.rs │ │ ├── htmlspanelement.rs │ │ ├── htmlunknownelement.rs │ │ ├── inheritance.rs │ │ ├── lib.rs │ │ ├── node.rs │ │ ├── nodetype.rs │ │ ├── parser.rs │ │ ├── str.rs │ │ ├── svgelement.rs │ │ ├── svggraphicselement.rs │ │ ├── svgsvgelement.rs │ │ ├── text.rs │ │ ├── virtualmethods.rs │ │ └── window.rs │ └── tests │ │ └── dom.rs └── layout │ ├── Cargo.toml │ ├── README.md │ ├── fonts │ └── Lato-Regular.ttf │ ├── src │ ├── applicable_declaration_block.rs │ ├── display_list │ │ ├── builder.rs │ │ ├── display_item.rs │ │ └── mod.rs │ ├── flow │ │ ├── block.rs │ │ ├── boxes.rs │ │ ├── formatting_context.rs │ │ ├── fragment.rs │ │ ├── inline.rs │ │ ├── mod.rs │ │ ├── text_run.rs │ │ └── tree.rs │ ├── fonts.rs │ ├── html.css │ ├── lib.rs │ ├── rule_colectors.rs │ ├── style_tree.rs │ └── text.rs │ └── tests │ ├── cascade.rs │ ├── cascade │ ├── background_color.rs │ ├── border_bottom_color.rs │ ├── border_bottom_style.rs │ ├── border_bottom_width.rs │ ├── border_left_color.rs │ ├── border_left_style.rs │ ├── border_left_width.rs │ ├── border_right_color.rs │ ├── border_right_style.rs │ ├── border_right_width.rs │ ├── border_top_color.rs │ ├── border_top_style.rs │ ├── border_top_width.rs │ ├── color.rs │ ├── display.rs │ ├── font_families.rs │ ├── font_size.rs │ ├── height.rs │ ├── margin_bottom.rs │ ├── margin_left.rs │ ├── margin_right.rs │ ├── margin_top.rs │ ├── max_height.rs │ ├── max_width.rs │ ├── min_height.rs │ ├── min_width.rs │ ├── padding_bottom.rs │ ├── padding_left.rs │ ├── padding_right.rs │ ├── padding_top.rs │ └── width.rs │ ├── flow.rs │ ├── flow │ ├── block.rs │ └── inline.rs │ └── setup │ └── mod.rs ├── docs └── design.md ├── examples └── rustlings │ ├── .all-contributorsrc │ ├── .clog.toml │ ├── .editorconfig │ ├── .gitignore │ ├── .gitpod.yml │ ├── .replit │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── Cargo.lock │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ ├── default_out.txt │ ├── exercises │ ├── README.md │ ├── clippy │ │ ├── README.md │ │ ├── clippy1.rs │ │ └── clippy2.rs │ ├── collections │ │ ├── README.md │ │ ├── hashmap1.rs │ │ ├── hashmap2.rs │ │ ├── vec1.rs │ │ └── vec2.rs │ ├── conversions │ │ ├── README.md │ │ ├── as_ref_mut.rs │ │ ├── from_into.rs │ │ ├── from_str.rs │ │ ├── try_from_into.rs │ │ └── using_as.rs │ ├── enums │ │ ├── README.md │ │ ├── enums1.rs │ │ ├── enums2.rs │ │ └── enums3.rs │ ├── error_handling │ │ ├── README.md │ │ ├── errors1.rs │ │ ├── errors2.rs │ │ ├── errors3.rs │ │ ├── errorsn.rs │ │ └── result1.rs │ ├── functions │ │ ├── README.md │ │ ├── functions1.rs │ │ ├── functions2.rs │ │ ├── functions3.rs │ │ ├── functions4.rs │ │ └── functions5.rs │ ├── generics │ │ ├── README.md │ │ ├── generics1.rs │ │ ├── generics2.rs │ │ └── generics3.rs │ ├── if │ │ ├── README.md │ │ ├── if1.rs │ │ └── if2.rs │ ├── macros │ │ ├── README.md │ │ ├── macros1.rs │ │ ├── macros2.rs │ │ ├── macros3.rs │ │ └── macros4.rs │ ├── modules │ │ ├── README.md │ │ ├── modules1.rs │ │ └── modules2.rs │ ├── move_semantics │ │ ├── README.md │ │ ├── move_semantics1.rs │ │ ├── move_semantics2.rs │ │ ├── move_semantics3.rs │ │ └── move_semantics4.rs │ ├── option │ │ ├── README.md │ │ ├── option1.rs │ │ └── option2.rs │ ├── primitive_types │ │ ├── README.md │ │ ├── primitive_types1.rs │ │ ├── primitive_types2.rs │ │ ├── primitive_types3.rs │ │ ├── primitive_types4.rs │ │ ├── primitive_types5.rs │ │ └── primitive_types6.rs │ ├── quiz1.rs │ ├── quiz2.rs │ ├── quiz3.rs │ ├── quiz4.rs │ ├── standard_library_types │ │ ├── README.md │ │ ├── arc1.rs │ │ ├── box1.rs │ │ ├── iterators1.rs │ │ ├── iterators2.rs │ │ ├── iterators3.rs │ │ ├── iterators4.rs │ │ └── iterators5.rs │ ├── strings │ │ ├── README.md │ │ ├── strings1.rs │ │ └── strings2.rs │ ├── structs │ │ ├── README.md │ │ ├── structs1.rs │ │ ├── structs2.rs │ │ └── structs3.rs │ ├── tests │ │ ├── README.md │ │ ├── tests1.rs │ │ ├── tests2.rs │ │ └── tests3.rs │ ├── threads │ │ ├── README.md │ │ └── threads1.rs │ ├── traits │ │ ├── README.md │ │ ├── traits1.rs │ │ └── traits2.rs │ └── variables │ │ ├── README.md │ │ ├── variables1.rs │ │ ├── variables2.rs │ │ ├── variables3.rs │ │ ├── variables4.rs │ │ ├── variables5.rs │ │ └── variables6.rs │ ├── info.toml │ ├── install.ps1 │ ├── install.sh │ ├── src │ ├── exercise.rs │ ├── main.rs │ ├── run.rs │ ├── ui.rs │ └── verify.rs │ └── tests │ ├── fixture │ ├── failure │ │ ├── compFailure.rs │ │ ├── compNoExercise.rs │ │ ├── info.toml │ │ ├── testFailure.rs │ │ └── testNotPassed.rs │ ├── state │ │ ├── finished_exercise.rs │ │ ├── info.toml │ │ ├── pending_exercise.rs │ │ └── pending_test_exercise.rs │ └── success │ │ ├── compSuccess.rs │ │ ├── info.toml │ │ └── testSuccess.rs │ └── integration_tests.rs ├── rustfmt.toml └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | examples/demo 2 | 3 | 4 | # Added by cargo 5 | 6 | /target 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mbrowser" 3 | version = "0.1.0" 4 | edition = "2018" 5 | resolver = "2" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | common = { path = "components/common" } 11 | dom = { path = "components/dom" } 12 | css = { path = "components/css" } 13 | layout = { path = "components/layout" } 14 | cssparser = "0.28.1" 15 | html5ever = "0.25.1" 16 | selectors = "0.23.0" 17 | wgpu = "0.11.0" 18 | wgpu_glyph = "0.15.1" 19 | glyph_brush = "0.7" 20 | iced_wgpu = { git = "https://github.com/iced-rs/iced" } 21 | iced_winit = { git = "https://github.com/iced-rs/iced" } 22 | 23 | [workspace] 24 | members = [ 25 | "components/common", 26 | "components/dom", 27 | "components/css", 28 | "components/layout", 29 | ] 30 | -------------------------------------------------------------------------------- /components/common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "common" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | url = "2.2.2" 10 | -------------------------------------------------------------------------------- /components/common/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod url; 2 | pub mod vector; 3 | 4 | #[macro_export] 5 | macro_rules! not_reached { 6 | () => (panic!("not be reached")); 7 | ($($arg:tt)+) => (panic!("not be reached: {}", $crate::format_args!($($arg)+))); 8 | } 9 | 10 | #[macro_export] 11 | macro_rules! not_supported { 12 | () => (panic!("not yet supported")); 13 | ($($arg:tt)+) => (panic!("not yet supported: {}", $crate::format_args!($($arg)+))); 14 | } 15 | -------------------------------------------------------------------------------- /components/common/src/vector.rs: -------------------------------------------------------------------------------- 1 | use std::slice::Iter; 2 | 3 | pub fn permutate<'t1, 't2, T1: Sized, T2: Sized>( 4 | iter1: Iter<'t1, T1>, 5 | iter2: Iter<'t2, T2>, 6 | ) -> Vec<(&'t1 T1, &'t2 T2)> { 7 | let mut ret = Vec::with_capacity(1); 8 | for e1 in iter1 { 9 | for e2 in iter2.clone() { 10 | ret.push((e1, e2)); 11 | } 12 | } 13 | ret 14 | } 15 | -------------------------------------------------------------------------------- /components/css/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "css" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | common = { path = "../common" } 10 | cssparser = "0.28.1" 11 | html5ever = "0.25.1" 12 | bitflags = "1.1.2" 13 | selectors = "0.23.0" 14 | string_cache = "0.8.1" 15 | smallbitvec = "2.3.0" 16 | regex = "1.5.4" 17 | dyn-fmt = "0.3.0" 18 | precomputed-hash = "0.1.1" 19 | murmur3 = "0.5.1" 20 | num_enum = "0.5.4" 21 | euclid = "0.22.6" 22 | -------------------------------------------------------------------------------- /components/css/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate bitflags; 3 | 4 | pub mod computed_values; 5 | pub mod css_writer; 6 | pub mod element_state; 7 | pub mod error_reporting; 8 | pub mod media_queries; 9 | pub mod parser; 10 | pub mod properties; 11 | pub mod selectors; 12 | pub mod str; 13 | pub mod stylesheets; 14 | pub mod stylist; 15 | pub mod values; 16 | 17 | pub type LocalName = values::GenericAtomIdent; 18 | pub type Namespace = values::GenericAtomIdent; 19 | pub type Prefix = values::GenericAtomIdent; 20 | -------------------------------------------------------------------------------- /components/css/src/media_queries/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod media_condition; 2 | pub mod media_feature_expression; 3 | pub mod media_features; 4 | pub mod media_list; 5 | pub mod media_query; 6 | -------------------------------------------------------------------------------- /components/css/src/properties/custom_properties.rs: -------------------------------------------------------------------------------- 1 | /// Parse a custom property name. 2 | /// 3 | /// 4 | pub fn parse_name(s: &str) -> Result<&str, ()> { 5 | if s.starts_with("--") { 6 | Ok(&s[2..]) 7 | } else { 8 | Err(()) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/block_size.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::Size; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-block-size 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Size::parse(input).map(PropertyDeclaration::BlockSize) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_block_end_color.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::color::Color; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-block-end-color 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Color::parse(input).map(PropertyDeclaration::BorderBlockEndColor) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_block_end_style.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::LineStyle; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-block-end-style 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineStyle::parse(input).map(PropertyDeclaration::BorderBlockEndStyle) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_block_end_width.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::line::LineWidth; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-end-width 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineWidth::parse(input).map(PropertyDeclaration::BorderBlockEndWidth) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_block_start_color.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::color::Color; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-block-end-color 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Color::parse(input).map(PropertyDeclaration::BorderBlockStartColor) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_block_start_style.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::LineStyle; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-block-start-style 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineStyle::parse(input).map(PropertyDeclaration::BorderBlockStartStyle) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_block_start_width.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::line::LineWidth; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-start-width 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineWidth::parse(input).map(PropertyDeclaration::BorderBlockStartWidth) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_bottom_left_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-backgrounds/#propdef-border-bottom-left-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderBottomLeftRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_bottom_right_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-backgrounds/#propdef-border-bottom-right-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderBottomRightRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_collapse.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css2/#borders 9 | #[derive(Clone, Debug)] 10 | pub enum BorderCollapse { 11 | Separate, 12 | Collapse, 13 | } 14 | 15 | property_keywords_impl! { BorderCollapse, 16 | BorderCollapse::Separate, "separate", 17 | BorderCollapse::Collapse, "collapse", 18 | } 19 | 20 | pub fn parse_declared<'i, 't>( 21 | _context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | BorderCollapse::parse(input).map(PropertyDeclaration::BorderCollapse) 25 | } 26 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_end_end_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-end-end-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderEndEndRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_end_start_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-end-start-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderEndStartRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_image_outset.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthOrNumberRect; 7 | 8 | /// https://drafts.csswg.org/css-backgrounds/#the-border-image-outset 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthOrNumberRect::parse(input).map(PropertyDeclaration::BorderImageOutset) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_inline_end_color.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::color::Color; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-end-color 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Color::parse(input).map(PropertyDeclaration::BorderInlineEndColor) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_inline_end_style.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::LineStyle; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-end-color 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineStyle::parse(input).map(PropertyDeclaration::BorderInlineEndStyle) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_inline_end_width.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::line::LineWidth; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-end-width 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineWidth::parse(input).map(PropertyDeclaration::BorderInlineEndWidth) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_inline_start_color.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::color::Color; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-start-color 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Color::parse(input).map(PropertyDeclaration::BorderInlineStartColor) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_inline_start_style.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::LineStyle; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-start-color 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineStyle::parse(input).map(PropertyDeclaration::BorderInlineStartStyle) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_inline_start_width.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::line::LineWidth; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-inline-start-width 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineWidth::parse(input).map(PropertyDeclaration::BorderInlineStartWidth) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_spacing.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::{NonNegativeLength, Pair}; 7 | 8 | /// https://drafts.csswg.org/css2/#separated-borders 9 | pub type BorderSpacing = Pair; 10 | 11 | impl BorderSpacing { 12 | pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { 13 | Pair::parse_with(input, |input| NonNegativeLength::parse(input)) 14 | } 15 | } 16 | 17 | pub fn parse_declared<'i, 't>( 18 | _context: &ParserContext, 19 | input: &mut Parser<'i, 't>, 20 | ) -> Result> { 21 | BorderSpacing::parse(input).map(PropertyDeclaration::BorderSpacing) 22 | } 23 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_start_end_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-start-end-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderStartEndRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_start_start_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-border-start-start-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderStartStartRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_top_left_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-backgrounds-3/#propdef-border-top-left-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderTopLeftRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/border_top_right_radius.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::border::BorderCornerRadius; 7 | 8 | /// https://drafts.csswg.org/css-backgrounds-3/#propdef-border-top-right-radius 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | BorderCornerRadius::parse(input).map(PropertyDeclaration::BorderTopRightRadius) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/bottom.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-position/#propdef-bottom 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::Bottom) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/box_sizing.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css-sizing/#box-sizing 9 | #[derive(Clone, Debug)] 10 | pub enum BoxSizing { 11 | ContentBox, 12 | BorderBox, 13 | } 14 | 15 | property_keywords_impl! { BoxSizing, 16 | BoxSizing::ContentBox, "content-box", 17 | BoxSizing::BorderBox, "border-box", 18 | } 19 | 20 | pub fn parse_declared<'i, 't>( 21 | _context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | BoxSizing::parse(input).map(PropertyDeclaration::BoxSizing) 25 | } 26 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/caption_side.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css-logical/#caption-side 9 | #[derive(Clone, Debug)] 10 | pub enum CaptionSide { 11 | Top, 12 | Bottom, 13 | } 14 | 15 | property_keywords_impl! { CaptionSide, 16 | CaptionSide::Top, "top", 17 | CaptionSide::Bottom, "bottom", 18 | } 19 | 20 | pub fn parse_declared<'i, 't>( 21 | _context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | CaptionSide::parse(input).map(PropertyDeclaration::CaptionSide) 25 | } 26 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/column_gap.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthPercentageOrNormal; 7 | 8 | /// https://drafts.csswg.org/css-align-3/#propdef-column-gap 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthPercentageOrNormal::parse(input).map(PropertyDeclaration::ColumnGap) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/column_width.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-multicol-1/#cw 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthOrAuto::parse(input).map(PropertyDeclaration::ColumnWidth) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/counter_increment.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::counter::CounterWithInteger; 7 | 8 | /// https://drafts.csswg.org/css-lists/#propdef-counter-increment 9 | pub fn parse_declared<'i, 't>( 10 | context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | CounterWithInteger::parse(context, input).map(PropertyDeclaration::CounterIncrement) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/counter_set.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::counter::CounterWithInteger; 7 | 8 | /// https://drafts.csswg.org/css-lists/#propdef-counter-set 9 | pub fn parse_declared<'i, 't>( 10 | context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | CounterWithInteger::parse(context, input).map(PropertyDeclaration::CounterSet) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/direction.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css-writing-modes/#direction 9 | #[derive(Clone, Debug)] 10 | pub enum Direction { 11 | Ltr, 12 | Rtl, 13 | } 14 | 15 | property_keywords_impl! { Direction, 16 | Direction::Ltr, "ltr", 17 | Direction::Rtl, "rtl", 18 | } 19 | 20 | pub fn parse_declared<'i, 't>( 21 | _context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | Direction::parse(input).map(PropertyDeclaration::Direction) 25 | } 26 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/empty_cells.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css2/#empty-cells 9 | #[derive(Clone, Debug)] 10 | pub enum EmptyCells { 11 | Show, 12 | Hide, 13 | } 14 | 15 | property_keywords_impl! { EmptyCells, 16 | EmptyCells::Show, "show", 17 | EmptyCells::Hide, "hide", 18 | } 19 | 20 | pub fn parse_declared<'i, 't>( 21 | _context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | EmptyCells::parse(input).map(PropertyDeclaration::EmptyCells) 25 | } 26 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/flex_grow.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::number::NonNegativeNumber; 7 | 8 | /// https://drafts.csswg.org/css-flexbox/#flex-grow-property 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeNumber::parse(input).map(PropertyDeclaration::FlexGrow) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/flex_shrink.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::number::NonNegativeNumber; 7 | 8 | /// https://drafts.csswg.org/css-flexbox/#flex-shrink-property 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeNumber::parse(input).map(PropertyDeclaration::FlexShrink) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/flex_wrap.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css-flexbox/#flex-wrap-property 9 | #[derive(Clone, Debug)] 10 | pub enum FlexWrap { 11 | Nowrap, 12 | Wrap, 13 | WrapReverse, 14 | } 15 | 16 | property_keywords_impl! { FlexWrap, 17 | FlexWrap::Nowrap, "no-wrap", 18 | FlexWrap::Wrap, "wrap", 19 | FlexWrap::WrapReverse, "wrap-reverse", 20 | } 21 | 22 | pub fn parse_declared<'i, 't>( 23 | _context: &ParserContext, 24 | input: &mut Parser<'i, 't>, 25 | ) -> Result> { 26 | FlexWrap::parse(input).map(PropertyDeclaration::FlexWrap) 27 | } 28 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/inline_size.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::Size; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-inline-size 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Size::parse(input).map(PropertyDeclaration::InlineSize) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/inset_block_end.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-inset-block-end 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::InsetBlockEnd) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/inset_block_start.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-inset-block-start 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::InsetBlockStart) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/inset_inline_end.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-inset-inline-end 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::InsetInlineEnd) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/inset_inline_start.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-inset-inline-start 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::InsetInlineStart) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/left.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-position/#propdef-left 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::Left) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/letter_spacing.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrNormal; 7 | 8 | /// https://drafts.csswg.org/css-text/#letter-spacing-property 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrNormal::parse(input).map(PropertyDeclaration::LetterSpacing) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/line_height.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthPercentageNumberOrNormal; 7 | 8 | /// https://drafts.csswg.org/css-inline/#line-height-property 9 | pub type LineHeight = NonNegativeLengthPercentageNumberOrNormal; 10 | 11 | pub fn parse_declared<'i, 't>( 12 | _context: &ParserContext, 13 | input: &mut Parser<'i, 't>, 14 | ) -> Result> { 15 | LineHeight::parse(input).map(PropertyDeclaration::LineHeight) 16 | } 17 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/margin_block_end.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical-1/#propdef-margin-block-end 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::MarginBlockEnd) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/margin_block_start.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical-1/#propdef-margin-block-start 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::MarginBlockStart) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/margin_inline_end.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical-1/#propdef-margin-inline-end 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::MarginInlineEnd) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/margin_inline_start.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-logical-1/#propdef-margin-inline-start 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::MarginInlineStart) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/max_block_size.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::Size; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-max-block-size 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Size::parse(input).map(PropertyDeclaration::MaxBlockSize) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/max_inline_size.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::Size; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-max-inline-size 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Size::parse(input).map(PropertyDeclaration::MaxInlineSize) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/min_block_size.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::Size; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-min-block-size 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Size::parse(input).map(PropertyDeclaration::MinBlockSize) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/min_inline_size.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::Size; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-min-inline-size 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Size::parse(input).map(PropertyDeclaration::MinInlineSize) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/opacity.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::number::NumberOrPercentage; 7 | 8 | /// https://drafts.csswg.org/css-color/#transparency 9 | pub type Opacity = NumberOrPercentage; 10 | 11 | pub fn parse_declared<'i, 't>( 12 | _context: &ParserContext, 13 | input: &mut Parser<'i, 't>, 14 | ) -> Result> { 15 | Opacity::parse(input).map(PropertyDeclaration::Opacity) 16 | } 17 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/order.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::number::Integer; 7 | 8 | /// https://drafts.csswg.org/css-display/#order-property 9 | pub fn parse_declared<'i, 't>( 10 | context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Integer::parse(context, input).map(PropertyDeclaration::Order) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/outline_offset.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::Length; 7 | 8 | /// https://drafts.csswg.org/css-ui/#outline-offset 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Length::parse(input).map(PropertyDeclaration::OutlineOffset) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/outline_width.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::line::LineWidth; 7 | 8 | /// https://drafts.csswg.org/css-ui/#outline-width 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LineWidth::parse(input).map(PropertyDeclaration::OutlineWidth) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/overflow_block.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::Overflow; 7 | 8 | /// https://drafts.csswg.org/css-overflow/#propdef-overflow-block 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Overflow::parse(input).map(PropertyDeclaration::OverflowBlock) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/overflow_inline.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::Overflow; 7 | 8 | /// https://drafts.csswg.org/css-overflow/#propdef-overflow-inline 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Overflow::parse(input).map(PropertyDeclaration::OverflowInline) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/overflow_x.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::Overflow; 7 | 8 | /// https://drafts.csswg.org/css-overflow/#propdef-overflow-x 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Overflow::parse(input).map(PropertyDeclaration::OverflowX) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/overflow_y.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::layout::Overflow; 7 | 8 | /// https://drafts.csswg.org/css-overflow/#propdef-overflow-y 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Overflow::parse(input).map(PropertyDeclaration::OverflowY) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/padding_block_end.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthPercentage; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-padding-block-end 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthPercentage::parse(input).map(PropertyDeclaration::PaddingBlockEnd) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/padding_block_start.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthPercentage; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-padding-block-start 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthPercentage::parse(input).map(PropertyDeclaration::PaddingBlockStart) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/padding_inline_end.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthPercentage; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-padding-inline-end 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthPercentage::parse(input).map(PropertyDeclaration::PaddingInlineEnd) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/padding_inline_start.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthPercentage; 7 | 8 | /// https://drafts.csswg.org/css-logical/#propdef-padding-inline-start 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthPercentage::parse(input).map(PropertyDeclaration::PaddingInlineStart) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/perspective.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::NonNegativeLengthOrNone; 7 | 8 | /// https://drafts.csswg.org/css-transforms-2/#perspective-property 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | NonNegativeLengthOrNone::parse(input).map(PropertyDeclaration::Perspective) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/perspective_origin.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::position::Position; 7 | 8 | /// https://drafts.csswg.org/css-transforms-2/#perspective-origin-property 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | Position::parse(input).map(PropertyDeclaration::PerspectiveOrigin) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/right.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-position/#propdef-right 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::Right) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/table_layout.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css2/#width-layout 9 | #[derive(Clone, Debug)] 10 | pub enum TableLayout { 11 | Auto, 12 | Fixed, 13 | } 14 | 15 | property_keywords_impl! { TableLayout, 16 | TableLayout::Auto, "auto", 17 | TableLayout::Fixed, "fixed", 18 | } 19 | 20 | pub fn parse_declared<'i, 't>( 21 | _context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | TableLayout::parse(input).map(PropertyDeclaration::TableLayout) 25 | } 26 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/top.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrAuto; 7 | 8 | /// https://drafts.csswg.org/css-position/#propdef-top 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrAuto::parse(input).map(PropertyDeclaration::Top) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/transform_style.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css-transforms-2/#transform-style-property 9 | #[derive(Clone, Debug)] 10 | pub enum TransformStyle { 11 | Flat, 12 | Preserve3d, 13 | } 14 | 15 | property_keywords_impl! { TransformStyle, 16 | TransformStyle::Flat, "flat", 17 | TransformStyle::Preserve3d, "preserve-3d", 18 | } 19 | 20 | pub fn parse_declared<'i, 't>( 21 | _context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | TransformStyle::parse(input).map(PropertyDeclaration::TransformStyle) 25 | } 26 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/visibility.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::{property_keywords_impl, PropertyDeclaration}; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | use crate::stylesheets::stylesheet::ParserContext; 7 | 8 | /// https://drafts.csswg.org/css2/#visibility 9 | #[derive(Clone, Debug)] 10 | pub enum Visibility { 11 | Visible, 12 | Hidden, 13 | Collapse, 14 | } 15 | 16 | property_keywords_impl! { Visibility, 17 | Visibility::Visible, "visible", 18 | Visibility::Hidden, "hidden", 19 | Visibility::Collapse, "collapse", 20 | } 21 | 22 | pub fn parse_declared<'i, 't>( 23 | _context: &ParserContext, 24 | input: &mut Parser<'i, 't>, 25 | ) -> Result> { 26 | Visibility::parse(input).map(PropertyDeclaration::Visibility) 27 | } 28 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/word_spacing.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::length::LengthPercentageOrNormal; 7 | 8 | /// https://drafts.csswg.org/css-text/#word-spacing-property 9 | pub fn parse_declared<'i, 't>( 10 | _context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | LengthPercentageOrNormal::parse(input).map(PropertyDeclaration::WordSpacing) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/longhands/z_index.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::PropertyDeclaration; 5 | use crate::stylesheets::stylesheet::ParserContext; 6 | use crate::values::specified::number::IntegerAuto; 7 | 8 | /// https://drafts.csswg.org/css2/#z-index 9 | pub fn parse_declared<'i, 't>( 10 | context: &ParserContext, 11 | input: &mut Parser<'i, 't>, 12 | ) -> Result> { 13 | IntegerAuto::parse(context, input).map(PropertyDeclaration::ZIndex) 14 | } 15 | -------------------------------------------------------------------------------- /components/css/src/properties/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod custom_properties; 2 | pub mod declaration; 3 | pub mod declaration_block; 4 | pub mod longhand_id; 5 | pub mod longhands; 6 | pub mod property_id; 7 | pub mod shorthand_id; 8 | pub mod shorthands; 9 | 10 | bitflags! { 11 | #[repr(C)] 12 | /// https://www.w3.org/TR/CSS22/cascade.html#specificity 13 | pub struct SelectorSpecificity: u32 { 14 | const ELEMENT = 1 << 0; 15 | const ATTRIBUTE = 1 << 10; 16 | const ID = 1 << 20; 17 | const STYLE = 1 << 30; 18 | const IMPORTANT = 1 << 31; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/src/selectors/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod nonts_pseudo_class; 2 | pub mod pseudo_element; 3 | pub mod select; 4 | pub mod selector_parser; 5 | -------------------------------------------------------------------------------- /components/css/src/str.rs: -------------------------------------------------------------------------------- 1 | /// Returns true if a given string has a given prefix with case-insensitive match. 2 | pub fn starts_with_ignore_ascii_case(string: &str, prefix: &str) -> bool { 3 | string.len() >= prefix.len() && string.as_bytes()[0..prefix.len()].eq_ignore_ascii_case(prefix.as_bytes()) 4 | } 5 | 6 | pub fn convert_options_to_string(options: Vec>, delimitor: &str) -> String { 7 | options 8 | .iter() 9 | .filter_map(|v| v.as_ref()) 10 | .map(|v| v.to_owned()) 11 | .collect::>() 12 | .join(delimitor) 13 | } 14 | 15 | pub fn join_strings(values: Vec<&str>, delimitor: &str) -> String { 16 | values 17 | .iter() 18 | .filter(|v| v.len() > 0) 19 | .map(|v| v.to_string()) 20 | .collect::>() 21 | .join(delimitor) 22 | } 23 | -------------------------------------------------------------------------------- /components/css/src/stylesheets/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod css_rule; 2 | pub mod keyframe_rule; 3 | pub mod media_rule; 4 | pub mod namespace_rule; 5 | pub mod origin; 6 | pub mod page_rule; 7 | pub mod rule_parser; 8 | pub mod style_rule; 9 | pub mod stylesheet; 10 | pub mod support_rule; 11 | -------------------------------------------------------------------------------- /components/css/src/stylesheets/origin.rs: -------------------------------------------------------------------------------- 1 | /// Each style rule has an origin, which determines where it enters the cascade. 2 | /// 3 | /// 4 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 5 | #[repr(u8)] 6 | pub enum Origin { 7 | /// 8 | UserAgent = 0x1, 9 | 10 | /// 11 | Author = 0x2, 12 | } 13 | -------------------------------------------------------------------------------- /components/css/src/values/computed/line.rs: -------------------------------------------------------------------------------- 1 | use super::length::NonNegativeLength; 2 | 3 | #[derive(Clone, Debug, PartialEq)] 4 | pub enum LineWidth { 5 | Thin, 6 | Medium, 7 | Thick, 8 | Length(NonNegativeLength), 9 | } 10 | -------------------------------------------------------------------------------- /components/css/src/values/generics/border.rs: -------------------------------------------------------------------------------- 1 | use cssparser::ToCss; 2 | 3 | use crate::values::specified::length::Pair; 4 | 5 | #[derive(Clone, Debug)] 6 | #[repr(C)] 7 | pub struct GenericBorderCornerRadius(pub Pair); 8 | 9 | impl ToCss for GenericBorderCornerRadius { 10 | fn to_css(&self, dest: &mut W) -> std::fmt::Result 11 | where 12 | W: std::fmt::Write, 13 | { 14 | self.0.to_css(dest) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /components/css/src/values/generics/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod border; 2 | pub mod counter; 3 | pub mod length; 4 | pub mod number; 5 | -------------------------------------------------------------------------------- /components/css/src/values/specified/border.rs: -------------------------------------------------------------------------------- 1 | use cssparser::Parser; 2 | 3 | use super::length::{NonNegativeLengthPercentage, Pair}; 4 | use crate::parser::ParseError; 5 | use crate::values::generics::border::GenericBorderCornerRadius; 6 | 7 | pub type BorderCornerRadius = GenericBorderCornerRadius; 8 | 9 | impl BorderCornerRadius { 10 | pub fn new(horizontal: NonNegativeLengthPercentage, vertical: NonNegativeLengthPercentage) -> Self { 11 | GenericBorderCornerRadius(Pair::new(horizontal, vertical)) 12 | } 13 | 14 | pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { 15 | let pair = Pair::parse_with(input, |input| NonNegativeLengthPercentage::parse(input))?; 16 | Ok(BorderCornerRadius::new(pair.0, pair.1)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /components/css/src/values/specified/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod angle; 2 | pub mod border; 3 | pub mod color; 4 | pub mod counter; 5 | pub mod easing; 6 | pub mod image; 7 | pub mod layout; 8 | pub mod leader; 9 | pub mod length; 10 | pub mod line; 11 | pub mod number; 12 | pub mod percentage; 13 | pub mod position; 14 | pub mod quote; 15 | pub mod target; 16 | pub mod time; 17 | pub mod transform; 18 | -------------------------------------------------------------------------------- /components/css/src/values/specified/quote.rs: -------------------------------------------------------------------------------- 1 | use cssparser::{match_ignore_ascii_case, Parser, ToCss, Token, _cssparser_internal_to_lowercase}; 2 | 3 | use crate::parser::ParseError; 4 | use crate::properties::declaration::property_keywords_impl; 5 | use crate::stylesheets::rule_parser::StyleParseErrorKind; 6 | 7 | /// https://drafts.csswg.org/css-content/#typedef-quote 8 | #[derive(Clone, Debug)] 9 | pub enum Quote { 10 | OpenQuote, 11 | CloseQuote, 12 | NoOpenQuote, 13 | NoCloseQuote, 14 | } 15 | 16 | property_keywords_impl! { Quote, 17 | Quote::OpenQuote, "open-quote", 18 | Quote::CloseQuote, "close-quote", 19 | Quote::NoOpenQuote, "no-open-quote", 20 | Quote::NoCloseQuote, "no-close-quote", 21 | } 22 | -------------------------------------------------------------------------------- /components/css/tests/keyframes.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | mod setup; 4 | 5 | #[test] 6 | pub fn parse_keyframes_string_from_to() { 7 | let css = r#"@keyframes "foo" { from {} to {} }"#; 8 | let (stylesheet, _) = parse(css); 9 | assert_css( 10 | &stylesheet, 11 | r#" 12 | @keyframes "foo" { 13 | 0% { 14 | } 15 | 100% { 16 | } 17 | } 18 | "#, 19 | ); 20 | } 21 | 22 | #[test] 23 | pub fn parse_keyframes_duplicate_in_selectors() { 24 | let css = r#" 25 | @keyframes identifier { 26 | 0% { 27 | } 28 | 50%, 50% { 29 | } 30 | 100% { 31 | } 32 | } 33 | "#; 34 | let (stylesheet, _) = parse(css); 35 | assert_css( 36 | &stylesheet, 37 | r#" 38 | @keyframes identifier { 39 | 0% { 40 | } 41 | 50% { 42 | } 43 | 100% { 44 | } 45 | } 46 | "#, 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /components/css/tests/namespace.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | mod setup; 4 | 5 | #[test] 6 | pub fn parse_namespace_with_string() { 7 | let css = r#" 8 | @namespace toto "http://toto.example.org"; 9 | @namespace "http://example.com/foo"; 10 | "#; 11 | let (stylesheet, _) = parse(css); 12 | assert_css(&stylesheet, css); 13 | } 14 | 15 | #[test] 16 | pub fn parse_namespace_with_url() { 17 | let css = r#" 18 | @namespace url(http://www.w3.org/1999/xhtml); 19 | @namespace svg url(http://www.w3.org/2000/svg);"#; 20 | let (stylesheet, _) = parse(css); 21 | assert_css(&stylesheet, css); 22 | } 23 | -------------------------------------------------------------------------------- /components/css/tests/page.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | mod setup; 4 | 5 | #[test] 6 | pub fn parse_page() { 7 | let css = r#" 8 | @page {} 9 | "#; 10 | let (stylesheet, _) = parse(css); 11 | assert_css(&stylesheet, css); 12 | } 13 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_delay.rs: -------------------------------------------------------------------------------- 1 | use setup::assert_property; 2 | use time::{second_or_milisecond_data, seconds_and_miliseconds_data}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | #[path = "../values/time.rs"] 8 | mod time; 9 | 10 | static TEMPLATE: &str = r#" 11 | .name {{ 12 | animation-delay: {}; 13 | }} 14 | "#; 15 | 16 | test_property!(second_or_milisecond, second_or_milisecond_data); 17 | 18 | test_property!(seconds_and_miliseconds, seconds_and_miliseconds_data); 19 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_direction.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | #[path = "../setup/mod.rs"] 4 | mod setup; 5 | 6 | #[test] 7 | pub fn keyword() { 8 | for prefix in ["normal", "reverse", "alternate", "alternate-reverse"].iter() { 9 | let css = &std::format!( 10 | r#" 11 | .name {{ 12 | animation-direction: {}; 13 | }} 14 | "#, 15 | prefix 16 | ); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn keywords() { 24 | let css = r#" 25 | .name { 26 | animation-direction: normal, reverse, alternate; 27 | } 28 | "#; 29 | let (stylesheet, _) = parse(css); 30 | assert_css(&stylesheet, css); 31 | } 32 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_duration.rs: -------------------------------------------------------------------------------- 1 | use setup::assert_property; 2 | use time::{second_or_milisecond_data, seconds_and_miliseconds_data}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | #[path = "../values/time.rs"] 8 | mod time; 9 | 10 | static TEMPLATE: &str = r#" 11 | .name {{ 12 | animation-duration: {}; 13 | }} 14 | "#; 15 | 16 | test_property!(second_or_milisecond, second_or_milisecond_data); 17 | 18 | test_property!(seconds_and_miliseconds, seconds_and_miliseconds_data); 19 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_fill_mode.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | #[path = "../setup/mod.rs"] 4 | mod setup; 5 | 6 | #[test] 7 | pub fn keyword() { 8 | for prefix in ["none", "forwards", "backwards", "both"].iter() { 9 | let css = &std::format!( 10 | r#" 11 | .name {{ 12 | animation-fill-mode: {}; 13 | }} 14 | "#, 15 | prefix 16 | ); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn keywords() { 24 | let css = r#" 25 | .name { 26 | animation-fill-mode: both, none, backwards; 27 | } 28 | "#; 29 | let (stylesheet, _) = parse(css); 30 | assert_css(&stylesheet, css); 31 | } 32 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_iteration_count.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | #[path = "../setup/mod.rs"] 4 | mod setup; 5 | 6 | #[test] 7 | pub fn keyword() { 8 | let css = r#" 9 | .name { 10 | animation-iteration-count: infinite; 11 | } 12 | "#; 13 | let (stylesheet, _) = parse(css); 14 | assert_css(&stylesheet, css); 15 | } 16 | 17 | #[test] 18 | pub fn number() { 19 | for value in ["0", "1", "500000", "0.25", "1.5"].iter() { 20 | let css = &std::format!( 21 | r#" 22 | .name {{ 23 | animation-iteration-count: {}; 24 | }} 25 | "#, 26 | value, 27 | ); 28 | let (stylesheet, _) = parse(css); 29 | assert_css(&stylesheet, css); 30 | } 31 | } 32 | 33 | #[test] 34 | pub fn mixed_keyword_and_number() { 35 | let css = r#" 36 | .name { 37 | animation-iteration-count: infinite, 0.25, 5; 38 | } 39 | "#; 40 | let (stylesheet, _) = parse(css); 41 | assert_css(&stylesheet, css); 42 | } 43 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_name.rs: -------------------------------------------------------------------------------- 1 | use animation::keyframe_name_data; 2 | use setup::{assert_css, assert_property, parse}; 3 | 4 | #[path = "../values/animation.rs"] 5 | mod animation; 6 | #[path = "../setup/mod.rs"] 7 | mod setup; 8 | 9 | const TEMPLATE: &str = r#" 10 | .name {{ 11 | animation-name: {}; 12 | }} 13 | "#; 14 | 15 | #[test] 16 | pub fn keyword() { 17 | let css = r#" 18 | .name { 19 | animation-name: none; 20 | } 21 | "#; 22 | let (stylesheet, _) = parse(css); 23 | assert_css(&stylesheet, css); 24 | } 25 | 26 | #[test] 27 | pub fn keyframe_name() { 28 | for (input, output) in keyframe_name_data().iter() { 29 | assert_property(TEMPLATE, input, output); 30 | } 31 | } 32 | 33 | #[test] 34 | pub fn mixed_keyword_and_keyframe_name() { 35 | let css = r#" 36 | .name { 37 | animation-name: none, momo, "hello"; 38 | } 39 | "#; 40 | let (stylesheet, _) = parse(css); 41 | assert_css(&stylesheet, css); 42 | } 43 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_play_state.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | #[path = "../setup/mod.rs"] 4 | mod setup; 5 | 6 | #[test] 7 | pub fn keyword() { 8 | for prefix in ["running", "paused"].iter() { 9 | let css = &std::format!( 10 | r#" 11 | .name {{ 12 | animation-play-state: {}; 13 | }} 14 | "#, 15 | prefix 16 | ); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn keywords() { 24 | let css = r#" 25 | .name { 26 | animation-play-state: running, running, paused; 27 | } 28 | "#; 29 | let (stylesheet, _) = parse(css); 30 | assert_css(&stylesheet, css); 31 | } 32 | -------------------------------------------------------------------------------- /components/css/tests/properties/animation_timing_function.rs: -------------------------------------------------------------------------------- 1 | use easing::{ 2 | cubic_bezier_function_data, cubic_bezier_keyword_data, linear_data, step_function_data, 3 | step_function_only_steps_data, step_keyword_data, 4 | }; 5 | use setup::assert_property; 6 | 7 | #[path = "../values/easing.rs"] 8 | mod easing; 9 | #[macro_use] 10 | #[path = "../setup/mod.rs"] 11 | mod setup; 12 | 13 | const TEMPLATE: &str = r#" 14 | .name {{ 15 | animation-timing-function: {}; 16 | }} 17 | "#; 18 | 19 | test_property!(linear, linear_data); 20 | 21 | test_property!(cubic_bezier_keyword, cubic_bezier_keyword_data); 22 | 23 | test_property!(cubic_bezier_function, cubic_bezier_function_data); 24 | 25 | test_property!(step_keyword, step_keyword_data); 26 | 27 | test_property!(step_function, step_function_data); 28 | 29 | test_property!(step_function_only_steps, step_function_only_steps_data); 30 | -------------------------------------------------------------------------------- /components/css/tests/properties/backface_visibility.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | #[path = "../setup/mod.rs"] 4 | mod setup; 5 | 6 | #[test] 7 | pub fn keyword() { 8 | for prefix in ["visible", "hidden"].iter() { 9 | let css = &std::format!( 10 | r#" 11 | .name {{ 12 | backface-visibility: {}; 13 | }} 14 | "#, 15 | prefix 16 | ); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/background_attachment.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | #[path = "../setup/mod.rs"] 4 | mod setup; 5 | 6 | #[test] 7 | pub fn keyword() { 8 | for prefix in ["scroll", "fixed", "local"].iter() { 9 | let css = &std::format!( 10 | r#" 11 | .name {{ 12 | background-attachment: {}; 13 | }} 14 | "#, 15 | prefix 16 | ); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn keywords() { 24 | let css = r#" 25 | .name { 26 | background-attachment: local, local, fixed; 27 | } 28 | "#; 29 | let (stylesheet, _) = parse(css); 30 | assert_css(&stylesheet, css); 31 | } 32 | -------------------------------------------------------------------------------- /components/css/tests/properties/background_clip.rs: -------------------------------------------------------------------------------- 1 | use setup::{assert_css, parse}; 2 | 3 | #[path = "../setup/mod.rs"] 4 | mod setup; 5 | 6 | #[test] 7 | pub fn keyword() { 8 | for prefix in ["border-box", "padding-box", "content-box"].iter() { 9 | let css = &std::format!( 10 | r#" 11 | .name {{ 12 | background-clip: {}; 13 | }} 14 | "#, 15 | prefix 16 | ); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn keywords() { 24 | let css = r#" 25 | .name { 26 | background-clip: padding-box, border-box, padding-box; 27 | } 28 | "#; 29 | let (stylesheet, _) = parse(css); 30 | assert_css(&stylesheet, css); 31 | } 32 | -------------------------------------------------------------------------------- /components/css/tests/properties/background_origin.rs: -------------------------------------------------------------------------------- 1 | use layout::box_data; 2 | use setup::{assert_css, assert_property, parse}; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | background-origin: {}; 13 | }}"#; 14 | 15 | test_property!(keyword, box_data); 16 | 17 | #[test] 18 | pub fn keywords() { 19 | let css = r#" 20 | .name { 21 | background-origin: border-box, content-box, content-box, padding-box; 22 | } 23 | "#; 24 | let (stylesheet, _) = parse(css); 25 | assert_css(&stylesheet, css); 26 | } 27 | -------------------------------------------------------------------------------- /components/css/tests/properties/block_size.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | block-size: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_block_end_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-block-end-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_block_end_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-block-start-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_block_start_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-block-end-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_block_start_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-block-start-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_bottom_left_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-bottom-left-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_bottom_right_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-bottom-right-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_bottom_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-bottom-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_bottom_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-bottom-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_collapse.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[path = "../setup/mod.rs"] 5 | mod setup; 6 | 7 | const TEMPLATE: &str = r#" 8 | .name {{ 9 | border-collapse: {}; 10 | }}"#; 11 | 12 | #[test] 13 | pub fn keyword() { 14 | for value in ["separate", "collapse"].iter() { 15 | let css = &TEMPLATE.format(&[&value]); 16 | let (stylesheet, _) = parse(css); 17 | assert_css(&stylesheet, css); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_end_end_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-end-end-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_end_start_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-end-start-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_image_outset.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_or_number_rect_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-image-outset: {}; 13 | }}"#; 14 | 15 | test_property!(rect, non_negative_length_or_number_rect_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_image_slice.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use number::non_negative_number_or_percentage_rect_data; 3 | use setup::{assert_css, assert_property, parse}; 4 | 5 | #[path = "../values/number.rs"] 6 | mod number; 7 | #[macro_use] 8 | #[path = "../setup/mod.rs"] 9 | mod setup; 10 | 11 | const TEMPLATE: &str = r#" 12 | .name {{ 13 | border-image-slice: {}; 14 | }}"#; 15 | 16 | test_property!(rect, non_negative_number_or_percentage_rect_data); 17 | 18 | #[test] 19 | pub fn rect_and_fill() { 20 | for (input, output) in [ 21 | ("0.25 fill", "0.25 0.25 0.25 0.25 fill"), 22 | ("fill 1% 5", "1% 5 1% 5 fill"), 23 | ] 24 | .iter() 25 | { 26 | let cin = &TEMPLATE.format(&[&input]); 27 | let cout = &TEMPLATE.format(&[&output]); 28 | let (stylesheet, _) = parse(cin); 29 | assert_css(&stylesheet, cout); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_image_width.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_or_number_rect_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-image-width: {}; 13 | }}"#; 14 | 15 | test_property!(rect, non_negative_length_percentage_or_number_rect_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_inline_end_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-inline-end-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_inline_end_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-inline-end-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_inline_start_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-inline-start-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_inline_start_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-inline-start-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_left_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-left-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_left_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-left-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_right_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-right-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_right_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-right-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_start_end_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-start-end-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_start_start_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-start-start-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_top_left_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-top-left-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_top_right_radius.rs: -------------------------------------------------------------------------------- 1 | use border::border_corner_radius_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/border.rs"] 5 | mod border; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-top-right-radius: {}; 13 | }}"#; 14 | 15 | test_property!(border_corner_radius, border_corner_radius_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_top_style.rs: -------------------------------------------------------------------------------- 1 | use layout::line_style_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-top-style: {}; 13 | }}"#; 14 | 15 | test_property!(line_style, line_style_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/border_top_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | border-top-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/bottom.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | bottom: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/box_sizing.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[path = "../values/color.rs"] 5 | mod color; 6 | #[path = "../setup/mod.rs"] 7 | mod setup; 8 | 9 | const TEMPLATE: &str = r#" 10 | .name {{ 11 | box-sizing: {}; 12 | }}"#; 13 | 14 | #[test] 15 | pub fn keyword() { 16 | for value in ["content-box", "border-box"].iter() { 17 | let css = &TEMPLATE.format(&[&value]); 18 | let (stylesheet, _) = parse(css); 19 | assert_css(&stylesheet, css); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /components/css/tests/properties/caption_side.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[path = "../values/color.rs"] 5 | mod color; 6 | #[path = "../setup/mod.rs"] 7 | mod setup; 8 | 9 | const TEMPLATE: &str = r#" 10 | .name {{ 11 | caption-side: {}; 12 | }}"#; 13 | 14 | #[test] 15 | pub fn keyword() { 16 | for value in ["top", "bottom"].iter() { 17 | let css = &TEMPLATE.format(&[&value]); 18 | let (stylesheet, _) = parse(css); 19 | assert_css(&stylesheet, css); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /components/css/tests/properties/clear.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[path = "../values/color.rs"] 5 | mod color; 6 | #[path = "../setup/mod.rs"] 7 | mod setup; 8 | 9 | const TEMPLATE: &str = r#" 10 | .name {{ 11 | clear: {}; 12 | }}"#; 13 | 14 | #[test] 15 | pub fn keyword() { 16 | for value in ["none", "left", "right", "both", "inline-start", "inline-end"].iter() { 17 | let css = &TEMPLATE.format(&[&value]); 18 | let (stylesheet, _) = parse(css); 19 | assert_css(&stylesheet, css); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /components/css/tests/properties/clip.rs: -------------------------------------------------------------------------------- 1 | use length::length_or_auto_rect_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | clip: rect({}); 13 | }}"#; 14 | 15 | test_property!(length_or_auto_rect_auto, length_or_auto_rect_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/column_count.rs: -------------------------------------------------------------------------------- 1 | use setup::assert_property; 2 | 3 | #[macro_use] 4 | #[path = "../setup/mod.rs"] 5 | mod setup; 6 | 7 | const TEMPLATE: &str = r#" 8 | .name {{ 9 | column-count: {}; 10 | }}"#; 11 | 12 | pub fn integer_or_auto_data() -> Vec<(String, String)> { 13 | let mut data = Vec::with_capacity(1); 14 | for (input, output) in [("1", "1"), ("2", "2"), ("100", "100"), ("auto", "auto")].iter() { 15 | data.push((input.to_string(), output.to_string())) 16 | } 17 | data 18 | } 19 | 20 | test_property!(integer_or_auto, integer_or_auto_data); 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/column_gap.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_or_normal_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | column-gap: {}; 13 | }}"#; 14 | 15 | test_property!( 16 | non_negative_length_percentage_or_normal, 17 | non_negative_length_percentage_or_normal_data 18 | ); 19 | -------------------------------------------------------------------------------- /components/css/tests/properties/column_width.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | column-width: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_or_auto, non_negative_length_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/counter_increment.rs: -------------------------------------------------------------------------------- 1 | use counter::counter_with_integer_and_none_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/counter.rs"] 5 | mod counter; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | counter-increment: {}; 13 | }}"#; 14 | 15 | test_property!(counter_with_integer_and_none, counter_with_integer_and_none_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/counter_reset.rs: -------------------------------------------------------------------------------- 1 | use counter::{counter_with_integer_and_none_data, reversed_counter_with_integer_and_none_data}; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/counter.rs"] 5 | mod counter; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | counter-reset: {}; 13 | }}"#; 14 | 15 | test_property!(counter_with_integer_and_none, counter_with_integer_and_none_data); 16 | 17 | test_property!( 18 | reversed_counter_with_integer_and_none, 19 | reversed_counter_with_integer_and_none_data 20 | ); 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/counter_set.rs: -------------------------------------------------------------------------------- 1 | use counter::counter_with_integer_and_none_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/counter.rs"] 5 | mod counter; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | counter-set: {}; 13 | }}"#; 14 | 15 | test_property!(counter_with_integer_and_none, counter_with_integer_and_none_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/direction.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[path = "../setup/mod.rs"] 5 | mod setup; 6 | 7 | const TEMPLATE: &str = r#" 8 | .name {{ 9 | direction: {}; 10 | }}"#; 11 | 12 | #[test] 13 | pub fn keyword() { 14 | for value in ["ltr", "rtl"].iter() { 15 | let css = &TEMPLATE.format(&[&value]); 16 | let (stylesheet, _) = parse(css); 17 | assert_css(&stylesheet, css); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /components/css/tests/properties/empty_cells.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[path = "../setup/mod.rs"] 5 | mod setup; 6 | 7 | const TEMPLATE: &str = r#" 8 | .name {{ 9 | empty-cells: {}; 10 | }}"#; 11 | 12 | #[test] 13 | pub fn keyword() { 14 | for value in ["show", "hide"].iter() { 15 | let css = &TEMPLATE.format(&[&value]); 16 | let (stylesheet, _) = parse(css); 17 | assert_css(&stylesheet, css); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /components/css/tests/properties/flex_basis.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use length::size_data; 3 | use setup::{assert_css, assert_property, parse}; 4 | 5 | #[path = "../values/length.rs"] 6 | mod length; 7 | #[macro_use] 8 | #[path = "../setup/mod.rs"] 9 | mod setup; 10 | 11 | const TEMPLATE: &str = r#" 12 | .name {{ 13 | flex-basis: {}; 14 | }}"#; 15 | 16 | #[test] 17 | pub fn keyword() { 18 | for value in ["content"].iter() { 19 | let css = &TEMPLATE.format(&[&value]); 20 | let (stylesheet, _) = parse(css); 21 | assert_css(&stylesheet, css); 22 | } 23 | } 24 | 25 | test_property!(size, size_data); 26 | -------------------------------------------------------------------------------- /components/css/tests/properties/flex_direction.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | flex-direction: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["row", "row-reverse", "column", "column-reverse"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/flex_grow.rs: -------------------------------------------------------------------------------- 1 | use number::non_negative_number_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/number.rs"] 5 | mod number; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | flex-grow: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_number, non_negative_number_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/flex_shrink.rs: -------------------------------------------------------------------------------- 1 | use number::non_negative_number_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/number.rs"] 5 | mod number; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | flex-shrink: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_number, non_negative_number_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/flex_wrap.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | flex-wrap: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["no-wrap", "wrap", "wrap-reverse"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/float.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | float: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["left", "right", "none", "inline-start", "inline-end"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/font_stretch.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use percentage::percentage_data; 3 | use setup::{assert_css, assert_property, parse}; 4 | 5 | #[path = "../values/percentage.rs"] 6 | mod percentage; 7 | #[macro_use] 8 | #[path = "../setup/mod.rs"] 9 | mod setup; 10 | 11 | const TEMPLATE: &str = r#" 12 | .name {{ 13 | font-stretch: {}; 14 | }}"#; 15 | 16 | #[test] 17 | pub fn keyword() { 18 | for value in [ 19 | "normal", 20 | "ultra-condensed", 21 | "extra-condensed", 22 | "condensed", 23 | "semi-condensed", 24 | "semi-expanded", 25 | "expanded", 26 | "extra-expanded", 27 | "ultra-expanded", 28 | ] 29 | .iter() 30 | { 31 | let css = &TEMPLATE.format(&[&value]); 32 | let (stylesheet, _) = parse(css); 33 | assert_css(&stylesheet, css); 34 | } 35 | } 36 | 37 | test_property!(percentage, percentage_data); 38 | -------------------------------------------------------------------------------- /components/css/tests/properties/font_style.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | font-style: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["normal", "italic"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn oblique() { 24 | for (input, output) in [("oblique", "oblique 14deg"), ("oblique 2.5deg", "oblique 2.5deg")].iter() { 25 | let cin = &TEMPLATE.format(&[&input]); 26 | let cout = &TEMPLATE.format(&[&output]); 27 | let (stylesheet, _) = parse(cin); 28 | assert_css(&stylesheet, cout); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /components/css/tests/properties/font_variant_caps.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | font-variant-caps: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in [ 16 | "normal", 17 | "small-caps", 18 | "all-small-caps", 19 | "petite-caps", 20 | "all-petite-caps", 21 | "unicase", 22 | "titling-caps", 23 | ] 24 | .iter() 25 | { 26 | let css = &TEMPLATE.format(&[&value]); 27 | let (stylesheet, _) = parse(css); 28 | assert_css(&stylesheet, css); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /components/css/tests/properties/font_weight.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | font-weight: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["normal", "bold", "bolder", "lighter"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn absolute() { 24 | for value in ["100", "200", "300", "400", "500", "600", "700", "800", "900", "1000"].iter() { 25 | let css = &TEMPLATE.format(&[&value]); 26 | let (stylesheet, _) = parse(css); 27 | assert_css(&stylesheet, css); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /components/css/tests/properties/height.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | height: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/image_rendering.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | image-rendering: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["auto", "crips-edges", "pixelated"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/inline_size.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | inline-size: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/inset_block_end.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | inset-block-end: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/inset_block_start.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | inset-block-start: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/inset_inline_end.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | inset-inline-end: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/inset_inline_start.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | inset-inline-start: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/justify_content.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | justify-content: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in [ 16 | "flex-start", 17 | "stretch", 18 | "flex-end", 19 | "center", 20 | "space-between", 21 | "space-around", 22 | ] 23 | .iter() 24 | { 25 | let css = &TEMPLATE.format(&[&value]); 26 | let (stylesheet, _) = parse(css); 27 | assert_css(&stylesheet, css); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /components/css/tests/properties/left.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | left: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/letter_spacing.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_normal_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | letter-spacing: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_normal, length_percentage_or_normal_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/line_height.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_number_or_normal_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | line-height: {}; 13 | }}"#; 14 | 15 | test_property!( 16 | non_negative_length_percentage_number_or_normal, 17 | non_negative_length_percentage_number_or_normal_data 18 | ); 19 | -------------------------------------------------------------------------------- /components/css/tests/properties/list_style_position.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | list-style-position: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["inside", "outside"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/list_style_type.rs: -------------------------------------------------------------------------------- 1 | use content::counter_style_data; 2 | use dyn_fmt::AsStrFormatExt; 3 | use setup::{assert_css, assert_property, parse}; 4 | 5 | #[path = "../values/content.rs"] 6 | mod content; 7 | #[macro_use] 8 | #[path = "../setup/mod.rs"] 9 | mod setup; 10 | 11 | const TEMPLATE: &str = r#" 12 | .name {{ 13 | list-style-type: {}; 14 | }}"#; 15 | 16 | #[test] 17 | pub fn keyword() { 18 | for value in ["none", "\"hello world\""].iter() { 19 | let css = &TEMPLATE.format(&[&value]); 20 | let (stylesheet, _) = parse(css); 21 | assert_css(&stylesheet, css); 22 | } 23 | } 24 | 25 | test_property!(counter_style, counter_style_data); 26 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_block_end.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-block-end: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_block_start.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-block-start: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_bottom.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-bottom: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_inline_end.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-inline-end: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_inline_start.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-inline-start: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_left.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-left: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_right.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-right: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/margin_top.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | margin-top: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/max_block_size.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | max-block-size: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/max_height.rs: -------------------------------------------------------------------------------- 1 | use length::max_size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | max-height: {}; 13 | }}"#; 14 | 15 | test_property!(max_size, max_size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/max_inline_size.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | max-inline-size: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/max_width.rs: -------------------------------------------------------------------------------- 1 | use length::max_size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | max-width: {}; 13 | }}"#; 14 | 15 | test_property!(max_size, max_size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/min_block_size.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | min-block-size: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/min_height.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | min-height: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/min_inline_size.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | min-inline-size: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/min_width.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | min-width: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/mix_blend_mode.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | mix-blend-mode: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in [ 16 | "normal", 17 | "multiply", 18 | "screen", 19 | "overlay", 20 | "darken", 21 | "lighten", 22 | "color-dodge", 23 | "color-burn", 24 | "hard-light", 25 | "soft-light", 26 | "difference", 27 | "exclusion", 28 | "hue", 29 | "saturation", 30 | "color", 31 | "luminosity", 32 | ] 33 | .iter() 34 | { 35 | let css = &TEMPLATE.format(&[&value]); 36 | let (stylesheet, _) = parse(css); 37 | assert_css(&stylesheet, css); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /components/css/tests/properties/object_fit.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | object-fit: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["fill", "contain", "cover", "none", "scale-down"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/opacity.rs: -------------------------------------------------------------------------------- 1 | use number::number_or_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/number.rs"] 5 | mod number; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | opacity: {}; 13 | }}"#; 14 | 15 | test_property!(number_or_percentage, number_or_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/order.rs: -------------------------------------------------------------------------------- 1 | use number::integer_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/number.rs"] 5 | mod number; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | order: {}; 13 | }}"#; 14 | 15 | test_property!(integer, integer_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/outline_offset.rs: -------------------------------------------------------------------------------- 1 | use length::length_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | outline-offset: {}; 13 | }}"#; 14 | 15 | test_property!(length, length_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/outline_style.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use layout::line_style_data; 3 | use setup::{assert_css, assert_property, parse}; 4 | 5 | #[path = "../values/layout.rs"] 6 | mod layout; 7 | #[macro_use] 8 | #[path = "../setup/mod.rs"] 9 | mod setup; 10 | 11 | const TEMPLATE: &str = r#" 12 | .name {{ 13 | outline-style: {}; 14 | }}"#; 15 | 16 | #[test] 17 | pub fn invert() { 18 | for value in ["auto"].iter() { 19 | let css = &TEMPLATE.format(&[&value]); 20 | let (stylesheet, _) = parse(css); 21 | assert_css(&stylesheet, css); 22 | } 23 | } 24 | 25 | fn line_style_without_hidden_data() -> Vec<(String, String)> { 26 | let data = line_style_data(); 27 | data.iter() 28 | .filter(|(input, _output)| input != "hidden") 29 | .map(|(input, output)| (input.to_string(), output.to_string())) 30 | .collect::>() 31 | } 32 | 33 | test_property!(line_style, line_style_without_hidden_data); 34 | -------------------------------------------------------------------------------- /components/css/tests/properties/outline_width.rs: -------------------------------------------------------------------------------- 1 | use line::line_width_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/line.rs"] 5 | mod line; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | outline-width: {}; 13 | }}"#; 14 | 15 | test_property!(line_width, line_width_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/overflow_block.rs: -------------------------------------------------------------------------------- 1 | use layout::overflow_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | overflow-block: {}; 13 | }}"#; 14 | 15 | test_property!(keyword, overflow_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/overflow_inline.rs: -------------------------------------------------------------------------------- 1 | use layout::overflow_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | overflow-inline: {}; 13 | }}"#; 14 | 15 | test_property!(keyword, overflow_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/overflow_wrap.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | overflow-wrap: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for value in ["normal", "break-word", "anywhere"].iter() { 16 | let css = &TEMPLATE.format(&[&value]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/overflow_x.rs: -------------------------------------------------------------------------------- 1 | use layout::overflow_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | overflow-x: {}; 13 | }}"#; 14 | 15 | test_property!(keyword, overflow_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/overflow_y.rs: -------------------------------------------------------------------------------- 1 | use layout::overflow_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/layout.rs"] 5 | mod layout; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | overflow-y: {}; 13 | }}"#; 14 | 15 | test_property!(keyword, overflow_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_block_end.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-block-end: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_block_start.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-block-start: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_bottom.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-bottom: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_inline_end.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-inline-end: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_inline_start.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-inline-start: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_left.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-left: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_right.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-right: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/padding_top.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_percentage_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | padding-top: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_percentage, non_negative_length_percentage_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/perspective.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_or_none_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | perspective: {}; 13 | }}"#; 14 | 15 | test_property!(non_negative_length_or_none, non_negative_length_or_none_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/perspective_origin.rs: -------------------------------------------------------------------------------- 1 | use position::position_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/position.rs"] 5 | mod position; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | perspective-origin: {}; 13 | }}"#; 14 | 15 | test_property!(position, position_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/pointer_events.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | pointer-events: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for (input, output) in [ 16 | ("auto", "auto"), 17 | ("bounding-box", "bounding-box"), 18 | ("visiblePainted", "visiblepainted"), 19 | ("visibleFill", "visiblefill"), 20 | ("visibleStroke", "visiblestroke"), 21 | ("visible", "visible"), 22 | ("painted", "painted"), 23 | ("fill", "fill"), 24 | ("stroke", "stroke"), 25 | ("all", "all"), 26 | ("none", "none"), 27 | ] 28 | .iter() 29 | { 30 | let cin = &TEMPLATE.format(&[&input]); 31 | let cout = &TEMPLATE.format(&[&output]); 32 | let (stylesheet, _) = parse(cin); 33 | assert_css(&stylesheet, cout); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /components/css/tests/properties/position.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | position: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["static", "absolute", "relative", "fixed", "sticky"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/quotes.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | quotes: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["none", "auto"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn content() { 24 | for input in ["\"hello\" \"world\"", "\"hello\" \"darkness\" \"my old\" \"friend\""].iter() { 25 | let css = &TEMPLATE.format(&[&input]); 26 | let (stylesheet, _) = parse(css); 27 | assert_css(&stylesheet, css); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /components/css/tests/properties/right.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | right: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/table_layout.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | table-layout: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["auto", "fixed"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/text_align.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | text-align: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in [ 16 | "start", 17 | "end", 18 | "left", 19 | "right", 20 | "center", 21 | "justify", 22 | "match-parent", 23 | "justify-all", 24 | ] 25 | .iter() 26 | { 27 | let css = &TEMPLATE.format(&[&input]); 28 | let (stylesheet, _) = parse(css); 29 | assert_css(&stylesheet, css); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /components/css/tests/properties/text_decoration_line.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | text-decoration-line: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in [ 16 | "none", 17 | "underline", 18 | "overline", 19 | "line-through", 20 | "blink", 21 | "underline overline", 22 | "overline blink", 23 | "line-through blink", 24 | "underline overline line-through", 25 | "underline overline blink", 26 | "underline overline line-through blink", 27 | ] 28 | .iter() 29 | { 30 | let css = &TEMPLATE.format(&[&input]); 31 | let (stylesheet, _) = parse(css); 32 | assert_css(&stylesheet, css); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /components/css/tests/properties/text_indent.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | text-indent: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn content() { 15 | for input in [ 16 | "10px", 17 | "5.5%", 18 | "10px hanging", 19 | "20% each-line", 20 | "2.5px hanging each-line", 21 | ] 22 | .iter() 23 | { 24 | let css = &TEMPLATE.format(&[&input]); 25 | let (stylesheet, _) = parse(css); 26 | assert_css(&stylesheet, css); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /components/css/tests/properties/text_justify.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | text-justify: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn content() { 15 | for input in ["none", "auto", "inter-word", "inter-character"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/text_rendering.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | text-rendering: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for (input, output) in [ 16 | ("auto", "auto"), 17 | ("optimizeSpeed", "optimizespeed"), 18 | ("optimizeLegibility", "optimizelegibility"), 19 | ("geometricPrecision", "geometricprecision"), 20 | ] 21 | .iter() 22 | { 23 | let cin = &TEMPLATE.format(&[&input]); 24 | let cout = &TEMPLATE.format(&[&output]); 25 | let (stylesheet, _) = parse(cin); 26 | assert_css(&stylesheet, cout); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /components/css/tests/properties/text_transform.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | text-transform: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in [ 16 | "none", 17 | "capitalize", 18 | "uppercase", 19 | "lowercase", 20 | "full-width", 21 | "full-size-kana", 22 | "capitalize uppercase", 23 | "full-width full-size-kana", 24 | "capitalize lowercase full-width", 25 | "capitalize uppercase full-size-kana", 26 | "capitalize uppercase lowercase full-width", 27 | "capitalize uppercase lowercase full-size-kana", 28 | "capitalize uppercase lowercase full-width full-size-kana", 29 | ] 30 | .iter() 31 | { 32 | let css = &TEMPLATE.format(&[&input]); 33 | let (stylesheet, _) = parse(css); 34 | assert_css(&stylesheet, css); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /components/css/tests/properties/top.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | top: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_auto, length_percentage_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/transform.rs: -------------------------------------------------------------------------------- 1 | use setup::assert_property; 2 | use transform::transform_data; 3 | 4 | #[path = "../values/transform.rs"] 5 | mod transform; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | transform: {}; 13 | }}"#; 14 | 15 | test_property!(function, transform_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/transform_origin.rs: -------------------------------------------------------------------------------- 1 | use position::transform_origin_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/position.rs"] 5 | mod position; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | transform-origin: {}; 13 | }}"#; 14 | 15 | test_property!(position, transform_origin_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/transform_style.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | transform-style: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["flat", "preserve-3d"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/transition_delay.rs: -------------------------------------------------------------------------------- 1 | use setup::assert_property; 2 | use time::{second_or_milisecond_data, seconds_and_miliseconds_data}; 3 | 4 | #[path = "../values/time.rs"] 5 | mod time; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | transition-delay: {}; 13 | }}"#; 14 | 15 | test_property!(second_or_milisecond, second_or_milisecond_data); 16 | 17 | test_property!(seconds_and_miliseconds, seconds_and_miliseconds_data); 18 | -------------------------------------------------------------------------------- /components/css/tests/properties/transition_duration.rs: -------------------------------------------------------------------------------- 1 | use setup::assert_property; 2 | use time::{second_or_milisecond_data, seconds_and_miliseconds_data}; 3 | 4 | #[path = "../values/time.rs"] 5 | mod time; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | transition-duration: {}; 13 | }}"#; 14 | 15 | test_property!(second_or_milisecond, second_or_milisecond_data); 16 | 17 | test_property!(seconds_and_miliseconds, seconds_and_miliseconds_data); 18 | -------------------------------------------------------------------------------- /components/css/tests/properties/transition_property.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | transition-property: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["none", "all", "something"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn keywords() { 24 | for input in ["all, bla", "utopia, lala, eww"].iter() { 25 | let css = &TEMPLATE.format(&[&input]); 26 | let (stylesheet, _) = parse(css); 27 | assert_css(&stylesheet, css); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /components/css/tests/properties/transition_timing_function.rs: -------------------------------------------------------------------------------- 1 | use easing::{ 2 | cubic_bezier_function_data, cubic_bezier_keyword_data, linear_data, step_function_data, 3 | step_function_only_steps_data, step_keyword_data, 4 | }; 5 | use setup::assert_property; 6 | 7 | #[path = "../values/easing.rs"] 8 | mod easing; 9 | #[macro_use] 10 | #[path = "../setup/mod.rs"] 11 | mod setup; 12 | 13 | const TEMPLATE: &str = r#" 14 | .name {{ 15 | transition-timing-function: {}; 16 | }} 17 | "#; 18 | 19 | test_property!(linear, linear_data); 20 | 21 | test_property!(cubic_bezier_keyword, cubic_bezier_keyword_data); 22 | 23 | test_property!(cubic_bezier_function, cubic_bezier_function_data); 24 | 25 | test_property!(step_keyword, step_keyword_data); 26 | 27 | test_property!(step_function, step_function_data); 28 | 29 | test_property!(step_function_only_steps, step_function_only_steps_data); 30 | -------------------------------------------------------------------------------- /components/css/tests/properties/translate.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | translate: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["none"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | 22 | #[test] 23 | pub fn coordinate() { 24 | for (input, output) in [ 25 | ("10px", "10px 0px 0px"), 26 | ("2.5% 5.75px", "2.5% 5.75px 0px"), 27 | ("1px 0% 100px", "1px 0% 100px"), 28 | ] 29 | .iter() 30 | { 31 | let cin = &TEMPLATE.format(&[&input]); 32 | let cout = &TEMPLATE.format(&[&output]); 33 | let (stylesheet, _) = parse(cin); 34 | assert_css(&stylesheet, cout); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /components/css/tests/properties/unicode_bidi.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | unicode-bidi: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in [ 16 | "normal", 17 | "embed", 18 | "isolate", 19 | "bidi-override", 20 | "isolate-override", 21 | "plantext", 22 | ] 23 | .iter() 24 | { 25 | let css = &TEMPLATE.format(&[&input]); 26 | let (stylesheet, _) = parse(css); 27 | assert_css(&stylesheet, css); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /components/css/tests/properties/vertical_align.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use length::length_percentage_data; 3 | use setup::{assert_css, assert_property, parse}; 4 | 5 | #[path = "../values/length.rs"] 6 | mod length; 7 | #[macro_use] 8 | #[path = "../setup/mod.rs"] 9 | mod setup; 10 | 11 | const TEMPLATE: &str = r#" 12 | .name {{ 13 | vertical-align: {}; 14 | }}"#; 15 | 16 | #[test] 17 | pub fn keyword() { 18 | for input in [ 19 | "baseline", 20 | "sub", 21 | "super", 22 | "top", 23 | "text-top", 24 | "middle", 25 | "bottom", 26 | "text-bottom", 27 | ] 28 | .iter() 29 | { 30 | let css = &TEMPLATE.format(&[&input]); 31 | let (stylesheet, _) = parse(css); 32 | assert_css(&stylesheet, css); 33 | } 34 | } 35 | 36 | test_property!(length_percentage, length_percentage_data); 37 | -------------------------------------------------------------------------------- /components/css/tests/properties/visibility.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | visibility: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["visible", "hidden", "collapse"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/white_space.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | white-space: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["normal", "pre", "nowrap", "pre-wrap", "pre-line"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/width.rs: -------------------------------------------------------------------------------- 1 | use length::size_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | width: {}; 13 | }}"#; 14 | 15 | test_property!(size, size_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/word_break.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | word-break: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in ["normal", "break-all", "keep-all", "break-word"].iter() { 16 | let css = &TEMPLATE.format(&[&input]); 17 | let (stylesheet, _) = parse(css); 18 | assert_css(&stylesheet, css); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/properties/word_spacing.rs: -------------------------------------------------------------------------------- 1 | use length::length_percentage_or_normal_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/length.rs"] 5 | mod length; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | word-spacing: {}; 13 | }}"#; 14 | 15 | test_property!(length_percentage_or_normal, length_percentage_or_normal_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/properties/writing_mode.rs: -------------------------------------------------------------------------------- 1 | use dyn_fmt::AsStrFormatExt; 2 | use setup::{assert_css, parse}; 3 | 4 | #[macro_use] 5 | #[path = "../setup/mod.rs"] 6 | mod setup; 7 | 8 | const TEMPLATE: &str = r#" 9 | .name {{ 10 | writing-mode: {}; 11 | }}"#; 12 | 13 | #[test] 14 | pub fn keyword() { 15 | for input in [ 16 | "horizontal-tb", 17 | "vertical-rl", 18 | "vertical-lr", 19 | "sideways-rl", 20 | "sideways-lr", 21 | ] 22 | .iter() 23 | { 24 | let css = &TEMPLATE.format(&[&input]); 25 | let (stylesheet, _) = parse(css); 26 | assert_css(&stylesheet, css); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /components/css/tests/properties/z_index.rs: -------------------------------------------------------------------------------- 1 | use number::integer_or_auto_data; 2 | use setup::assert_property; 3 | 4 | #[path = "../values/number.rs"] 5 | mod number; 6 | #[macro_use] 7 | #[path = "../setup/mod.rs"] 8 | mod setup; 9 | 10 | const TEMPLATE: &str = r#" 11 | .name {{ 12 | z-index: {}; 13 | }}"#; 14 | 15 | test_property!(integer_or_auto, integer_or_auto_data); 16 | -------------------------------------------------------------------------------- /components/css/tests/shorthands.rs: -------------------------------------------------------------------------------- 1 | mod shorthands { 2 | pub mod border_color; 3 | pub mod border_style; 4 | pub mod border_width; 5 | pub mod margin; 6 | pub mod margin_block; 7 | pub mod margin_inline; 8 | pub mod padding; 9 | pub mod padding_block; 10 | pub mod padding_inline; 11 | } 12 | -------------------------------------------------------------------------------- /components/css/tests/values.rs: -------------------------------------------------------------------------------- 1 | mod values { 2 | mod angle; 3 | mod animation; 4 | mod border; 5 | mod color; 6 | mod content; 7 | mod counter; 8 | mod easing; 9 | mod filter; 10 | mod image; 11 | mod layout; 12 | mod length; 13 | mod line; 14 | mod number; 15 | mod percentage; 16 | mod position; 17 | mod time; 18 | mod transform; 19 | mod url; 20 | } 21 | -------------------------------------------------------------------------------- /components/css/tests/values/angle.rs: -------------------------------------------------------------------------------- 1 | use common::vector::permutate; 2 | 3 | pub fn angle_data() -> Vec<(String, String)> { 4 | let mut data = Vec::with_capacity(1); 5 | for (value, unit) in permutate(["0", "5.5", "360"].iter(), ["deg", "grad", "rad", "turn"].iter()).iter() { 6 | let input = std::format!("{}{}", value, unit); 7 | data.push((input.to_string(), input.to_string())); 8 | } 9 | data 10 | } 11 | 12 | pub fn angle_or_zero_data() -> Vec<(String, String)> { 13 | let mut data = angle_data(); 14 | data.push(("0".to_string(), "0".to_string())); 15 | data 16 | } 17 | -------------------------------------------------------------------------------- /components/css/tests/values/animation.rs: -------------------------------------------------------------------------------- 1 | pub fn keyframe_name_data() -> Vec<(String, String)> { 2 | let mut data = Vec::with_capacity(1); 3 | for name in ["nono79", "ground-level", "-test", "_internal", "chào", "\"hello\""].iter() { 4 | data.push((name.to_string(), name.to_string())) 5 | } 6 | data 7 | } 8 | -------------------------------------------------------------------------------- /components/css/tests/values/border.rs: -------------------------------------------------------------------------------- 1 | pub fn border_corner_radius_data() -> Vec<(String, String)> { 2 | let mut data = Vec::with_capacity(1); 3 | for (input, output) in [("0px", "0px 0px"), ("5.5px 12.5%", "5.5px 12.5%")].iter() { 4 | data.push((input.to_string(), output.to_string())) 5 | } 6 | data 7 | } 8 | -------------------------------------------------------------------------------- /components/css/tests/values/counter.rs: -------------------------------------------------------------------------------- 1 | pub fn counter_with_integer_and_none_data() -> Vec<(String, String)> { 2 | let mut data = Vec::with_capacity(1); 3 | for value in ["none", "something", "bla 0", "lalala -10 utopia", "ping pong ping pong"].iter() { 4 | data.push((value.to_string(), value.to_string())) 5 | } 6 | data 7 | } 8 | 9 | pub fn reversed_counter_with_integer_and_none_data() -> Vec<(String, String)> { 10 | let mut data = Vec::with_capacity(1); 11 | for value in [ 12 | "none", 13 | "reversed(something)", 14 | "reversed(bla) 0", 15 | "reversed(lalala) -10 reversed(utopia)", 16 | "reversed(ping) reversed(pong) reversed(ping) reversed(pong)", 17 | ] 18 | .iter() 19 | { 20 | data.push((value.to_string(), value.to_string())) 21 | } 22 | data 23 | } 24 | -------------------------------------------------------------------------------- /components/css/tests/values/line.rs: -------------------------------------------------------------------------------- 1 | use length::non_negative_length_data; 2 | 3 | #[path = "./length.rs"] 4 | mod length; 5 | 6 | pub fn line_width_data() -> Vec<(String, String)> { 7 | let mut data = Vec::with_capacity(1); 8 | for (input, _) in non_negative_length_data().iter() { 9 | data.push((input.to_string(), input.to_string())); 10 | } 11 | for value in ["thin", "medium", "thick"].iter() { 12 | data.push((value.to_string(), value.to_string())); 13 | } 14 | data 15 | } 16 | -------------------------------------------------------------------------------- /components/css/tests/values/percentage.rs: -------------------------------------------------------------------------------- 1 | use common::vector::permutate; 2 | 3 | pub fn percentage_data() -> Vec<(String, String)> { 4 | let mut data = Vec::with_capacity(1); 5 | for value in ["0%", "10.5%", "100%"].iter() { 6 | data.push((value.to_string(), value.to_string())); 7 | } 8 | data 9 | } 10 | 11 | pub fn ratio_data() -> Vec<(String, String)> { 12 | let mut data = Vec::with_capacity(1); 13 | for (first, second) in permutate(["0", "2.5", "10"].iter(), ["500", "1000.25", ""].iter()).iter() { 14 | let isecond = if second.len() == 0 { 15 | "".to_string() 16 | } else { 17 | std::format!(" / {}", second) 18 | }; 19 | let input = std::format!("{}{}", first, isecond); 20 | let osecond = if second.len() == 0 { "1" } else { second }; 21 | let output = std::format!("{} / {}", first, osecond); 22 | data.push((input, output)); 23 | } 24 | data 25 | } 26 | -------------------------------------------------------------------------------- /components/css/tests/values/time.rs: -------------------------------------------------------------------------------- 1 | use common::vector::permutate; 2 | 3 | pub fn second_or_milisecond_data() -> Vec<(String, String)> { 4 | let mut data = Vec::with_capacity(1); 5 | 6 | for (value, unit) in permutate(["0", "1", "500000", "0.25", "1.5"].iter(), ["s", "ms"].iter()) { 7 | let input = std::format!("{}{}", value, unit); 8 | let output = input.clone(); 9 | data.push((input, output)); 10 | } 11 | data 12 | } 13 | 14 | pub fn seconds_and_miliseconds_data() -> Vec<(String, String)> { 15 | let mut data = Vec::with_capacity(1); 16 | for value in ["0s, 1.5s, 30ms"].iter() { 17 | let input = value.to_string(); 18 | let output = input.clone(); 19 | data.push((input, output)); 20 | } 21 | data 22 | } 23 | -------------------------------------------------------------------------------- /components/css/tests/values/url.rs: -------------------------------------------------------------------------------- 1 | use common::vector::permutate; 2 | use dyn_fmt::AsStrFormatExt; 3 | 4 | pub fn url_data() -> Vec<(String, String)> { 5 | let mut data = Vec::with_capacity(1); 6 | for (input, output) in [( 7 | "url(http://www.example.org/style/basic.css)", 8 | r#"url("http://www.example.org/style/basic.css")"#, 9 | )] 10 | .iter() 11 | { 12 | data.push((input.to_string(), output.to_string())) 13 | } 14 | 15 | for ((name, value), modifier) in permutate( 16 | permutate( 17 | ["url({}{})", "src({}{})"].iter(), 18 | [r#""http://www.example.com/pinkish.gif""#].iter(), 19 | ) 20 | .iter(), 21 | ["", " prefetch", " var(--foo)", " defer toggle(italic, normal)"].iter(), 22 | ) 23 | .iter() 24 | { 25 | let input = name.format(&[value, modifier]); 26 | data.push((input.clone(), input.clone())); 27 | } 28 | data 29 | } 30 | -------------------------------------------------------------------------------- /components/dom/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dom" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | common = { path = "../common" } 10 | css = { path = "../css" } 11 | html5ever = "0.25.1" 12 | mime = "0.3.16" 13 | regex = "1.5.4" 14 | encoding_rs = "0.8.28" 15 | cssparser = "0.28.1" 16 | num-traits = "0.2.14" 17 | selectors = "0.23.0" 18 | euclid = "0.22.6" 19 | once_cell = "1.8.0" 20 | -------------------------------------------------------------------------------- /components/dom/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQuy/mbrowser/e9d54deb776b3284279e85e020829978d8285134/components/dom/README.md -------------------------------------------------------------------------------- /components/dom/src/cdatasection.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use crate::characterdata::CharacterData; 4 | use crate::document::Document; 5 | use crate::node::Node; 6 | use crate::nodetype::{CharacterDataTypeId, NodeTypeId, TextTypeId}; 7 | use crate::text::Text; 8 | 9 | #[derive(Clone)] 10 | #[repr(C)] 11 | pub struct CDATASection { 12 | text: Text, 13 | } 14 | 15 | impl crate::inheritance::Castable for CDATASection {} 16 | impl crate::inheritance::DerivedFrom for CDATASection {} 17 | impl crate::inheritance::DerivedFrom for CDATASection {} 18 | impl crate::inheritance::DerivedFrom for CDATASection {} 19 | 20 | impl CDATASection { 21 | pub fn new(text: String, document: Rc) -> Self { 22 | Self { 23 | text: Text::new_inherited( 24 | NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)), 25 | text, 26 | document, 27 | ), 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /components/dom/src/characterdata.rs: -------------------------------------------------------------------------------- 1 | use std::cell::{Ref, RefCell}; 2 | use std::rc::Rc; 3 | 4 | use crate::document::Document; 5 | use crate::inheritance::{Castable, DerivedFrom}; 6 | use crate::node::Node; 7 | use crate::nodetype::NodeTypeId; 8 | 9 | #[derive(Clone, Debug)] 10 | #[repr(C)] 11 | pub struct CharacterData { 12 | node: Node, 13 | data: RefCell, 14 | } 15 | 16 | impl CharacterData { 17 | pub fn new_inherited(node_type_id: NodeTypeId, data: String, document: Rc) -> Self { 18 | Self { 19 | node: Node::new(node_type_id, Some(document)), 20 | data: RefCell::new(data), 21 | } 22 | } 23 | 24 | #[inline] 25 | pub fn data(&self) -> Ref { 26 | self.data.borrow() 27 | } 28 | 29 | #[inline] 30 | pub fn append_data(&self, data: &str) { 31 | self.data.borrow_mut().push_str(data); 32 | } 33 | } 34 | 35 | impl Castable for CharacterData {} 36 | impl DerivedFrom for CharacterData {} 37 | -------------------------------------------------------------------------------- /components/dom/src/customelementregistry.rs: -------------------------------------------------------------------------------- 1 | use html5ever::LocalName; 2 | 3 | /// 4 | pub struct CustomElementDefinition { 5 | pub name: LocalName, 6 | pub local_name: LocalName, 7 | pub observed_attributes: Vec, 8 | } 9 | -------------------------------------------------------------------------------- /components/dom/src/documentfragment.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use crate::document::Document; 4 | use crate::inheritance::{Castable, DerivedFrom}; 5 | use crate::node::Node; 6 | use crate::nodetype::{DocumentFragmentTypeId, NodeTypeId}; 7 | 8 | #[derive(Clone)] 9 | #[repr(C)] 10 | pub struct DocumentFragment { 11 | node: Node, 12 | } 13 | 14 | impl DocumentFragment { 15 | pub fn new(document: Rc) -> Self { 16 | Self { 17 | node: Node::new( 18 | NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment), 19 | Some(document), 20 | ), 21 | } 22 | } 23 | } 24 | 25 | impl Castable for DocumentFragment {} 26 | impl DerivedFrom for DocumentFragment {} 27 | -------------------------------------------------------------------------------- /components/dom/src/documenttype.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | use crate::document::Document; 4 | use crate::node::Node; 5 | 6 | #[derive(Clone)] 7 | #[repr(C)] 8 | pub struct DocumentType { 9 | node: Node, 10 | name: String, 11 | public_id: String, 12 | system_id: String, 13 | } 14 | 15 | impl DocumentType { 16 | pub fn new(name: String, public_id: String, system_id: String, document: Rc) -> Self { 17 | DocumentType { 18 | node: Node::new(crate::nodetype::NodeTypeId::DocumentType, Some(document)), 19 | name, 20 | public_id, 21 | system_id, 22 | } 23 | } 24 | } 25 | 26 | impl crate::inheritance::Castable for DocumentType {} 27 | impl crate::inheritance::DerivedFrom for DocumentType {} 28 | -------------------------------------------------------------------------------- /components/dom/src/inheritance.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | pub trait DerivedFrom: Castable {} 4 | 5 | pub trait Castable: Sized { 6 | fn upcast(&self) -> &T 7 | where 8 | T: Castable, 9 | Self: DerivedFrom, 10 | { 11 | unsafe { &*(self as *const Self as *const T) } 12 | } 13 | 14 | fn downcast(&self) -> &T 15 | where 16 | T: DerivedFrom, 17 | { 18 | unsafe { &*(self as *const Self as *const T) } 19 | } 20 | } 21 | 22 | pub fn downcast>(node: Rc) -> Rc { 23 | unsafe { Rc::from_raw(Rc::into_raw(node) as *const U) } 24 | } 25 | 26 | pub fn upcast>(node: Rc) -> Rc { 27 | unsafe { Rc::from_raw(Rc::into_raw(node) as *const T) } 28 | } 29 | -------------------------------------------------------------------------------- /components/dom/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod attr; 2 | pub mod cdatasection; 3 | pub mod characterdata; 4 | pub mod comment; 5 | pub mod customelementregistry; 6 | pub mod document; 7 | pub mod documentfragment; 8 | pub mod documenttype; 9 | pub mod element; 10 | pub mod error; 11 | pub mod global_scope; 12 | pub mod htmlbaseelement; 13 | pub mod htmlbodyelement; 14 | pub mod htmldivelement; 15 | pub mod htmlelement; 16 | pub mod htmlheadelement; 17 | pub mod htmlheadingelement; 18 | pub mod htmlhtmlelement; 19 | pub mod htmlparagraphelement; 20 | pub mod htmlspanelement; 21 | pub mod htmlunknownelement; 22 | pub mod inheritance; 23 | pub mod node; 24 | pub mod nodetype; 25 | pub mod parser; 26 | pub mod str; 27 | pub mod svgelement; 28 | pub mod svggraphicselement; 29 | pub mod svgsvgelement; 30 | pub mod text; 31 | pub mod virtualmethods; 32 | pub mod window; 33 | -------------------------------------------------------------------------------- /components/layout/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "layout" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | common = { path = "../common" } 10 | css = { path = "../css" } 11 | dom = { path = "../dom" } 12 | cssparser = "0.28.1" 13 | html5ever = "0.25.1" 14 | selectors = "0.23.0" 15 | wgpu = "0.11.0" 16 | wgpu_glyph = "0.15.1" 17 | glyph_brush = "0.7" 18 | font-kit = "0.10.1" 19 | euclid = "0.22.6" 20 | serial_test = "0.5.1" 21 | once_cell = "1.8.0" 22 | regex = { version = "1.5.4", features = ["pattern"] } 23 | uuid = { version = "0.8.2", features = ["serde", "v4"] } 24 | -------------------------------------------------------------------------------- /components/layout/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQuy/mbrowser/e9d54deb776b3284279e85e020829978d8285134/components/layout/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /components/layout/src/display_list/display_item.rs: -------------------------------------------------------------------------------- 1 | use css::values::specified::color::RGBA; 2 | use css::values::{CSSFloat, CSSPixel, Pixel}; 3 | use euclid::Rect; 4 | 5 | pub type LayoutRect = Rect; 6 | 7 | #[derive(Debug)] 8 | pub struct RectangleDisplayItem { 9 | pub bounds: LayoutRect, 10 | pub color: RGBA, 11 | } 12 | 13 | #[derive(Debug)] 14 | pub struct TextDisplayItem { 15 | pub bounds: LayoutRect, 16 | pub content: String, 17 | pub color: RGBA, 18 | pub font_families: Vec, 19 | pub font_size: CSSFloat, 20 | } 21 | 22 | #[derive(Debug)] 23 | pub enum DisplayItem { 24 | Rectangle(RectangleDisplayItem), 25 | Text(TextDisplayItem), 26 | } 27 | -------------------------------------------------------------------------------- /components/layout/src/display_list/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod builder; 2 | pub mod display_item; 3 | -------------------------------------------------------------------------------- /components/layout/src/flow/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod block; 2 | pub mod boxes; 3 | pub mod formatting_context; 4 | pub mod fragment; 5 | pub mod inline; 6 | pub mod text_run; 7 | pub mod tree; 8 | -------------------------------------------------------------------------------- /components/layout/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(once_cell)] 2 | 3 | pub mod applicable_declaration_block; 4 | pub mod display_list; 5 | pub mod flow; 6 | pub mod fonts; 7 | pub mod rule_colectors; 8 | pub mod style_tree; 9 | pub mod text; 10 | -------------------------------------------------------------------------------- /components/layout/tests/cascade.rs: -------------------------------------------------------------------------------- 1 | mod cascade { 2 | pub mod background_color; 3 | pub mod border_bottom_color; 4 | pub mod border_bottom_style; 5 | pub mod border_bottom_width; 6 | pub mod border_left_color; 7 | pub mod border_left_style; 8 | pub mod border_left_width; 9 | pub mod border_right_color; 10 | pub mod border_right_style; 11 | pub mod border_right_width; 12 | pub mod border_top_color; 13 | pub mod border_top_style; 14 | pub mod border_top_width; 15 | pub mod color; 16 | pub mod display; 17 | pub mod font_families; 18 | pub mod font_size; 19 | pub mod height; 20 | pub mod margin_bottom; 21 | pub mod margin_left; 22 | pub mod margin_right; 23 | pub mod margin_top; 24 | pub mod max_height; 25 | pub mod max_width; 26 | pub mod min_height; 27 | pub mod min_width; 28 | pub mod padding_bottom; 29 | pub mod padding_left; 30 | pub mod padding_right; 31 | pub mod padding_top; 32 | pub mod width; 33 | } 34 | -------------------------------------------------------------------------------- /components/layout/tests/flow.rs: -------------------------------------------------------------------------------- 1 | mod flow { 2 | pub mod block; 3 | pub mod inline; 4 | } 5 | -------------------------------------------------------------------------------- /examples/rustlings/.clog.toml: -------------------------------------------------------------------------------- 1 | [clog] 2 | 3 | repository = "https://github.com/rust-lang/rustlings" 4 | changelog = "CHANGELOG.md" -------------------------------------------------------------------------------- /examples/rustlings/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.rs] 4 | end_of_line = lf 5 | insert_final_newfile = true 6 | indent_style = space 7 | indent_size = 4 8 | -------------------------------------------------------------------------------- /examples/rustlings/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | target/ 3 | **/*.rs.bk 4 | .DS_Store 5 | *.pdb 6 | exercises/clippy/Cargo.toml 7 | exercises/clippy/Cargo.lock 8 | .idea 9 | .vscode 10 | -------------------------------------------------------------------------------- /examples/rustlings/.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - init: /workspace/rustlings/install.sh 3 | command: /workspace/.cargo/bin/rustlings watch 4 | 5 | vscode: 6 | extensions: 7 | - rust-lang.rust@0.7.8:CvNqMTgDdt3UXt+6BCDTVg== 8 | -------------------------------------------------------------------------------- /examples/rustlings/.replit: -------------------------------------------------------------------------------- 1 | language = "rust" 2 | run = "[ -x ~/.cargo/bin/rustlings ] && ~/.cargo/bin/rustlings watch || ./install.sh" 3 | -------------------------------------------------------------------------------- /examples/rustlings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustlings" 3 | version = "4.4.0" 4 | authors = ["Marisa ", "Carol (Nichols || Goulding) "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | argh = "0.1.4" 9 | indicatif = "0.10.3" 10 | console = "0.7.7" 11 | notify = "4.0.15" 12 | toml = "0.4.10" 13 | regex = "1.1.6" 14 | serde = {version = "1.0.10", features = ["derive"]} 15 | 16 | [[bin]] 17 | name = "rustlings" 18 | path = "src/main.rs" 19 | 20 | [dev-dependencies] 21 | assert_cmd = "0.11.0" 22 | predicates = "1.0.1" 23 | glob = "0.3.0" 24 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/clippy/README.md: -------------------------------------------------------------------------------- 1 | # Clippy 2 | 3 | The Clippy tool is a collection of lints to analyze your code so you can catch common mistakes and improve your Rust code. 4 | 5 | If you used the installation script for Rustlings, Clippy should be already installed. 6 | If not you can install it manually via `rustup component add clippy`. 7 | 8 | ## Further information 9 | 10 | - [GitHub Repository](https://github.com/rust-lang/rust-clippy). 11 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/clippy/clippy1.rs: -------------------------------------------------------------------------------- 1 | // clippy1.rs 2 | // The Clippy tool is a collection of lints to analyze your code 3 | // so you can catch common mistakes and improve your Rust code. 4 | // 5 | // For these exercises the code will fail to compile when there are clippy warnings 6 | // check clippy's suggestions from the output to solve the exercise. 7 | // Execute `rustlings hint clippy1` for hints :) 8 | 9 | fn main() { 10 | let x = 1.2331f64; 11 | let y = 1.2332f64; 12 | if (y - x).abs() > f64::EPSILON { 13 | println!("Success!"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/clippy/clippy2.rs: -------------------------------------------------------------------------------- 1 | // clippy2.rs 2 | // Make me compile! Execute `rustlings hint clippy2` for hints :) 3 | 4 | fn main() { 5 | let mut res = 42; 6 | let option = Some(12); 7 | if let Some(x) = option { 8 | res += x; 9 | } 10 | println!("{}", res); 11 | } 12 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/collections/vec1.rs: -------------------------------------------------------------------------------- 1 | // vec1.rs 2 | // Your task is to create a `Vec` which holds the exact same elements 3 | // as in the array `a`. 4 | // Make me compile and pass the test! 5 | // Execute the command `rustlings hint vec1` if you need hints. 6 | 7 | fn array_and_vec() -> ([i32; 4], Vec) { 8 | let a = [10, 20, 30, 40]; // a plain array 9 | let v = vec![10, 20, 30, 40]; 10 | 11 | (a, v) 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | 18 | #[test] 19 | fn test_array_and_vec_similarity() { 20 | let (a, v) = array_and_vec(); 21 | assert_eq!(a, v[..]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/collections/vec2.rs: -------------------------------------------------------------------------------- 1 | // vec2.rs 2 | // A Vec of even numbers is given. Your task is to complete the loop 3 | // so that each number in the Vec is multiplied by 2. 4 | // 5 | // Make me pass the test! 6 | // 7 | // Execute the command `rustlings hint vec2` if you need 8 | // hints. 9 | 10 | fn vec_loop(mut v: Vec) -> Vec { 11 | for i in v.iter_mut() { 12 | *i = *i * 2; 13 | } 14 | 15 | // At this point, `v` should be equal to [4, 8, 12, 16, 20]. 16 | v 17 | } 18 | 19 | #[cfg(test)] 20 | mod tests { 21 | use super::*; 22 | 23 | #[test] 24 | fn test_vec_loop() { 25 | let v: Vec = (1..).filter(|x| x % 2 == 0).take(5).collect(); 26 | let ans = vec_loop(v.clone()); 27 | 28 | assert_eq!(ans, v.iter().map(|x| x * 2).collect::>()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/conversions/using_as.rs: -------------------------------------------------------------------------------- 1 | // Type casting in Rust is done via the usage of the `as` operator. 2 | // Please note that the `as` operator is not only used when type casting. 3 | // It also helps with renaming imports. 4 | // 5 | // The goal is to make sure that the division does not fail to compile 6 | // and returns the proper type. 7 | 8 | fn average(values: &[f64]) -> f64 { 9 | let total = values.iter().fold(0.0, |a, b| a + b); 10 | total / (values.len() as f64) 11 | } 12 | 13 | fn main() { 14 | let values = [3.5, 0.3, 13.0, 11.7]; 15 | println!("{}", average(&values)); 16 | } 17 | 18 | #[cfg(test)] 19 | mod tests { 20 | use super::*; 21 | 22 | #[test] 23 | fn returns_proper_type_and_value() { 24 | assert_eq!(average(&[3.5, 0.3, 13.0, 11.7]), 7.125); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/enums/README.md: -------------------------------------------------------------------------------- 1 | # Enums 2 | 3 | Rust allows you to define types called "enums" which enumerate possible values. 4 | Enums are a feature in many languages, but their capabilities differ in each language. Rust’s enums are most similar to algebraic data types in functional languages, such as F#, OCaml, and Haskell. 5 | Useful in combination with enums is Rust's "pattern matching" facility, which makes it easy to run different code for different values of an enumeration. 6 | 7 | ## Further information 8 | 9 | - [Enums](https://doc.rust-lang.org/book/ch06-00-enums.html) 10 | - [Pattern syntax](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html) 11 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/enums/enums1.rs: -------------------------------------------------------------------------------- 1 | // enums1.rs 2 | // Make me compile! Execute `rustlings hint enums1` for hints! 3 | 4 | #[derive(Debug)] 5 | enum Message { 6 | Quit, 7 | Echo, 8 | Move, 9 | ChangeColor, 10 | } 11 | 12 | fn main() { 13 | println!("{:?}", Message::Quit); 14 | println!("{:?}", Message::Echo); 15 | println!("{:?}", Message::Move); 16 | println!("{:?}", Message::ChangeColor); 17 | } 18 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/enums/enums2.rs: -------------------------------------------------------------------------------- 1 | // enums2.rs 2 | // Make me compile! Execute `rustlings hint enums2` for hints! 3 | 4 | #[derive(Debug)] 5 | enum Message { 6 | Move { x: u32, y: u32 }, 7 | Echo(String), 8 | ChangeColor(u32, u32, u32), 9 | Quit, 10 | } 11 | 12 | impl Message { 13 | fn call(&self) { 14 | println!("{:?}", &self); 15 | } 16 | } 17 | 18 | fn main() { 19 | let messages = [ 20 | Message::Move { x: 10, y: 30 }, 21 | Message::Echo(String::from("hello world")), 22 | Message::ChangeColor(200, 255, 255), 23 | Message::Quit, 24 | ]; 25 | 26 | for message in &messages { 27 | message.call(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/error_handling/README.md: -------------------------------------------------------------------------------- 1 | # Error handling 2 | Most errors aren’t serious enough to require the program to stop entirely. 3 | Sometimes, when a function fails, it’s for a reason that you can easily interpret and respond to. 4 | For example, if you try to open a file and that operation fails because the file doesn’t exist, you might want to create the file instead of terminating the process. 5 | 6 | ## Further information 7 | 8 | - [Error Handling](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html) 9 | - [Generics](https://doc.rust-lang.org/book/ch10-01-syntax.html) 10 | - [Result](https://doc.rust-lang.org/rust-by-example/error/result.html) 11 | - [Boxing errors](https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/boxing_errors.html) 12 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/functions/README.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | Here, you'll learn how to write functions and how Rust's compiler can trace things way back. 4 | 5 | ## Further information 6 | 7 | - [How Functions Work](https://doc.rust-lang.org/book/ch03-03-how-functions-work.html) 8 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/functions/functions1.rs: -------------------------------------------------------------------------------- 1 | // functions1.rs 2 | // Make me compile! Execute `rustlings hint functions1` for hints :) 3 | 4 | fn call_me() {} 5 | 6 | fn main() { 7 | call_me(); 8 | } 9 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/functions/functions2.rs: -------------------------------------------------------------------------------- 1 | // functions2.rs 2 | // Make me compile! Execute `rustlings hint functions2` for hints :) 3 | 4 | fn main() { 5 | call_me(3); 6 | } 7 | 8 | fn call_me(num: i32) { 9 | for i in 0..num { 10 | println!("Ring! Call number {}", i + 1); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/functions/functions3.rs: -------------------------------------------------------------------------------- 1 | // functions3.rs 2 | // Make me compile! Execute `rustlings hint functions3` for hints :) 3 | 4 | fn main() { 5 | call_me(3); 6 | } 7 | 8 | fn call_me(num: u32) { 9 | for i in 0..num { 10 | println!("Ring! Call number {}", i + 1); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/functions/functions4.rs: -------------------------------------------------------------------------------- 1 | // functions4.rs 2 | // Make me compile! Execute `rustlings hint functions4` for hints :) 3 | 4 | // This store is having a sale where if the price is an even number, you get 5 | // 10 Rustbucks off, but if it's an odd number, it's 3 Rustbucks off. 6 | 7 | fn main() { 8 | let original_price = 51; 9 | println!("Your sale price is {}", sale_price(original_price)); 10 | } 11 | 12 | fn sale_price(price: i32) -> i32 { 13 | if is_even(price) { 14 | price - 10 15 | } else { 16 | price - 3 17 | } 18 | } 19 | 20 | fn is_even(num: i32) -> bool { 21 | num % 2 == 0 22 | } 23 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/functions/functions5.rs: -------------------------------------------------------------------------------- 1 | // functions5.rs 2 | // Make me compile! Execute `rustlings hint functions5` for hints :) 3 | 4 | fn main() { 5 | let answer = square(3); 6 | println!("The answer is {}", answer); 7 | } 8 | 9 | fn square(num: i32) -> i32 { 10 | num * num 11 | } 12 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/generics/README.md: -------------------------------------------------------------------------------- 1 | # Generics 2 | 3 | Generics is the topic of generalizing types and functionalities to broader cases. 4 | This is extremely useful for reducing code duplication in many ways, but can call for rather involving syntax. 5 | Namely, being generic requires taking great care to specify over which types a generic type is actually considered valid. 6 | The simplest and most common use of generics is for type parameters. 7 | 8 | ## Further information 9 | 10 | - [Generic Data Types](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html) 11 | - [Bounds](https://doc.rust-lang.org/rust-by-example/generics/bounds.html) 12 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/generics/generics1.rs: -------------------------------------------------------------------------------- 1 | // This shopping list program isn't compiling! 2 | // Use your knowledge of generics to fix it. 3 | 4 | fn main() { 5 | let mut shopping_list: Vec<&str> = Vec::new(); 6 | shopping_list.push("milk"); 7 | } 8 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/generics/generics2.rs: -------------------------------------------------------------------------------- 1 | // This powerful wrapper provides the ability to store a positive integer value. 2 | // Rewrite it using generics so that it supports wrapping ANY type. 3 | 4 | struct Wrapper { 5 | value: T, 6 | } 7 | 8 | impl Wrapper { 9 | pub fn new(value: T) -> Self { 10 | Wrapper { value } 11 | } 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | 18 | #[test] 19 | fn store_u32_in_wrapper() { 20 | assert_eq!(Wrapper::new(42).value, 42); 21 | } 22 | 23 | #[test] 24 | fn store_str_in_wrapper() { 25 | assert_eq!(Wrapper::new("Foo").value, "Foo"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/if/README.md: -------------------------------------------------------------------------------- 1 | # If 2 | 3 | `if`, the most basic type of control flow, is what you'll learn here. 4 | 5 | ## Further information 6 | 7 | - [Control Flow - if expressions](https://doc.rust-lang.org/book/ch03-05-control-flow.html#if-expressions) 8 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/if/if1.rs: -------------------------------------------------------------------------------- 1 | // if1.rs 2 | 3 | pub fn bigger(a: i32, b: i32) -> i32 { 4 | if a > b { 5 | a 6 | } else { 7 | b 8 | } 9 | } 10 | 11 | // Don't mind this for now :) 12 | #[cfg(test)] 13 | mod tests { 14 | use super::*; 15 | 16 | #[test] 17 | fn ten_is_bigger_than_eight() { 18 | assert_eq!(10, bigger(10, 8)); 19 | } 20 | 21 | #[test] 22 | fn fortytwo_is_bigger_than_thirtytwo() { 23 | assert_eq!(42, bigger(32, 42)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/if/if2.rs: -------------------------------------------------------------------------------- 1 | // if2.rs 2 | 3 | // Step 1: Make me compile! 4 | // Step 2: Get the bar_for_fuzz and default_to_baz tests passing! 5 | // Execute the command `rustlings hint if2` if you want a hint :) 6 | 7 | pub fn fizz_if_foo(fizzish: &str) -> &str { 8 | if fizzish == "fizz" { 9 | "foo" 10 | } else if fizzish == "fuzz" { 11 | "bar" 12 | } else { 13 | "baz" 14 | } 15 | } 16 | 17 | // No test changes needed! 18 | #[cfg(test)] 19 | mod tests { 20 | use super::*; 21 | 22 | #[test] 23 | fn foo_for_fizz() { 24 | assert_eq!(fizz_if_foo("fizz"), "foo") 25 | } 26 | 27 | #[test] 28 | fn bar_for_fuzz() { 29 | assert_eq!(fizz_if_foo("fuzz"), "bar") 30 | } 31 | 32 | #[test] 33 | fn default_to_baz() { 34 | assert_eq!(fizz_if_foo("literally anything"), "baz") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/macros/README.md: -------------------------------------------------------------------------------- 1 | # Macros 2 | 3 | Rust's macro system is very powerful, but also kind of difficult to wrap your 4 | head around. We're not going to teach you how to write your own fully-featured 5 | macros. Instead, we'll show you how to use and create them. 6 | 7 | ## Further information 8 | 9 | - [Macros](https://doc.rust-lang.org/book/ch19-06-macros.html) 10 | - [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html) 11 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/macros/macros1.rs: -------------------------------------------------------------------------------- 1 | // macros1.rs 2 | // Make me compile! Execute `rustlings hint macros1` for hints :) 3 | 4 | macro_rules! my_macro { 5 | () => { 6 | println!("Check out my macro!"); 7 | }; 8 | } 9 | 10 | fn main() { 11 | my_macro!(); 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/macros/macros2.rs: -------------------------------------------------------------------------------- 1 | // macros2.rs 2 | // Make me compile! Execute `rustlings hint macros2` for hints :) 3 | 4 | macro_rules! my_macro { 5 | () => { 6 | println!("Check out my macro!"); 7 | }; 8 | } 9 | 10 | fn main() { 11 | my_macro!(); 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/macros/macros3.rs: -------------------------------------------------------------------------------- 1 | // macros3.rs 2 | // Make me compile, without taking the macro out of the module! 3 | // Execute `rustlings hint macros3` for hints :) 4 | 5 | #[macro_use] 6 | mod macros { 7 | macro_rules! my_macro { 8 | () => { 9 | println!("Check out my macro!"); 10 | }; 11 | } 12 | } 13 | 14 | fn main() { 15 | my_macro!(); 16 | } 17 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/macros/macros4.rs: -------------------------------------------------------------------------------- 1 | // macros4.rs 2 | // Make me compile! Execute `rustlings hint macros4` for hints :) 3 | 4 | macro_rules! my_macro { 5 | () => { 6 | println!("Check out my macro!"); 7 | }; 8 | ($val:expr) => { 9 | println!("Look at this other macro: {}", $val); 10 | }; 11 | } 12 | 13 | fn main() { 14 | my_macro!(); 15 | my_macro!(7777); 16 | } 17 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/modules/README.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | In this section we'll give you an introduction to Rust's module system. 4 | 5 | ## Further information 6 | 7 | - [The Module System](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html) 8 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/modules/modules1.rs: -------------------------------------------------------------------------------- 1 | // modules1.rs 2 | // Make me compile! Execute `rustlings hint modules1` for hints :) 3 | 4 | mod sausage_factory { 5 | pub fn make_sausage() { 6 | println!("sausage!"); 7 | } 8 | } 9 | 10 | fn main() { 11 | sausage_factory::make_sausage(); 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/modules/modules2.rs: -------------------------------------------------------------------------------- 1 | // modules2.rs 2 | // Make me compile! Execute `rustlings hint modules2` for hints :) 3 | 4 | mod delicious_snacks { 5 | pub use self::fruits::PEAR as fruit; 6 | pub use self::veggies::CUCUMBER as veggie; 7 | 8 | mod fruits { 9 | pub const PEAR: &'static str = "Pear"; 10 | pub const APPLE: &'static str = "Apple"; 11 | } 12 | 13 | mod veggies { 14 | pub const CUCUMBER: &'static str = "Cucumber"; 15 | pub const CARROT: &'static str = "Carrot"; 16 | } 17 | } 18 | 19 | fn main() { 20 | println!( 21 | "favorite snacks: {} and {}", 22 | delicious_snacks::fruit, 23 | delicious_snacks::veggie 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/move_semantics/README.md: -------------------------------------------------------------------------------- 1 | # Move Semantics 2 | 3 | These exercises are adapted from [pnkfelix](https://github.com/pnkfelix)'s [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- Thank you Felix!!! 4 | 5 | ## Further information 6 | 7 | For this section, the book links are especially important. 8 | 9 | - [Ownership](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html) 10 | - [Reference and borrowing](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html) 11 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/move_semantics/move_semantics1.rs: -------------------------------------------------------------------------------- 1 | // move_semantics1.rs 2 | // Make me compile! Execute `rustlings hint move_semantics1` for hints :) 3 | 4 | fn main() { 5 | let vec0 = Vec::new(); 6 | 7 | let mut vec1 = fill_vec(vec0); 8 | 9 | println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); 10 | 11 | vec1.push(88); 12 | 13 | println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); 14 | } 15 | 16 | fn fill_vec(vec: Vec) -> Vec { 17 | let mut vec = vec; 18 | 19 | vec.push(22); 20 | vec.push(44); 21 | vec.push(66); 22 | 23 | vec 24 | } 25 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/move_semantics/move_semantics2.rs: -------------------------------------------------------------------------------- 1 | // move_semantics2.rs 2 | // Make me compile without changing line 13! 3 | // Execute `rustlings hint move_semantics2` for hints :) 4 | 5 | fn main() { 6 | let vec0 = Vec::new(); 7 | 8 | let mut vec1 = fill_vec(vec0.clone()); 9 | 10 | // Do not change the following line! 11 | println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0); 12 | 13 | vec1.push(88); 14 | 15 | println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); 16 | } 17 | 18 | fn fill_vec(vec: Vec) -> Vec { 19 | let mut vec = vec; 20 | 21 | vec.push(22); 22 | vec.push(44); 23 | vec.push(66); 24 | 25 | vec 26 | } 27 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/move_semantics/move_semantics3.rs: -------------------------------------------------------------------------------- 1 | // move_semantics3.rs 2 | // Make me compile without adding new lines-- just changing existing lines! 3 | // (no lines with multiple semicolons necessary!) 4 | // Execute `rustlings hint move_semantics3` for hints :) 5 | 6 | fn main() { 7 | let vec0 = Vec::new(); 8 | 9 | let mut vec1 = fill_vec(vec0); 10 | 11 | println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); 12 | 13 | vec1.push(88); 14 | 15 | println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); 16 | } 17 | 18 | fn fill_vec(mut vec: Vec) -> Vec { 19 | vec.push(22); 20 | vec.push(44); 21 | vec.push(66); 22 | 23 | vec 24 | } 25 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/move_semantics/move_semantics4.rs: -------------------------------------------------------------------------------- 1 | // move_semantics4.rs 2 | // Refactor this code so that instead of having `vec0` and creating the vector 3 | // in `fn main`, we create it within `fn fill_vec` and transfer the 4 | // freshly created vector from fill_vec to its caller. 5 | // Execute `rustlings hint move_semantics4` for hints! 6 | 7 | fn main() { 8 | let mut vec1 = fill_vec(); 9 | 10 | println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); 11 | 12 | vec1.push(88); 13 | 14 | println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); 15 | } 16 | 17 | // `fill_vec()` no longer takes `vec: Vec` as argument 18 | fn fill_vec() -> Vec { 19 | let mut vec = Vec::new(); 20 | 21 | vec.push(22); 22 | vec.push(44); 23 | vec.push(66); 24 | 25 | vec 26 | } 27 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/option/option1.rs: -------------------------------------------------------------------------------- 1 | // option1.rs 2 | // Make me compile! Execute `rustlings hint option1` for hints 3 | 4 | // you can modify anything EXCEPT for this function's sig 5 | fn print_number(maybe_number: Option) { 6 | println!("printing: {}", maybe_number.unwrap()); 7 | } 8 | 9 | fn main() { 10 | print_number(Some(13)); 11 | print_number(Some(99)); 12 | 13 | let mut numbers: [Option; 5] = [Some(2), Some(3), Some(1), Some(4), Some(0)]; 14 | for iter in 0..5 { 15 | let number_to_add: u16 = { ((iter * 1235) + 2) / (4 * 16) }; 16 | 17 | numbers[iter as usize] = Some(number_to_add); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/option/option2.rs: -------------------------------------------------------------------------------- 1 | // option2.rs 2 | // Make me compile! Execute `rustlings hint option2` for hints 3 | 4 | fn main() { 5 | let optional_word = Some(String::from("rustlings")); 6 | if let Some(word) = optional_word { 7 | println!("The word is: {}", word); 8 | } else { 9 | println!("The optional word doesn't contain anything"); 10 | } 11 | 12 | let mut optional_integers_vec: Vec> = Vec::new(); 13 | for x in 1..10 { 14 | optional_integers_vec.push(Some(x)); 15 | } 16 | 17 | // You can stack `Option`'s into while let and if let 18 | while let Some(Some(integer)) = optional_integers_vec.pop() { 19 | println!("current value: {}", integer); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/primitive_types/README.md: -------------------------------------------------------------------------------- 1 | # Primitive Types 2 | 3 | Rust has a couple of basic types that are directly implemented into the 4 | compiler. In this section, we'll go through the most important ones. 5 | 6 | ## Further information 7 | 8 | - [Data Types](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html) 9 | - [The Slice Type](https://doc.rust-lang.org/stable/book/ch04-03-slices.html) 10 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/primitive_types/primitive_types1.rs: -------------------------------------------------------------------------------- 1 | // primitive_types1.rs 2 | // Fill in the rest of the line that has code missing! 3 | // No hints, there's no tricks, just get used to typing these :) 4 | 5 | fn main() { 6 | // Booleans (`bool`) 7 | 8 | let is_morning = true; 9 | if is_morning { 10 | println!("Good morning!"); 11 | } 12 | 13 | let is_evening = false; // Finish the rest of this line like the example! Or make it be false! 14 | if is_evening { 15 | println!("Good evening!"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/primitive_types/primitive_types3.rs: -------------------------------------------------------------------------------- 1 | // primitive_types3.rs 2 | // Create an array with at least 100 elements in it where the ??? is. 3 | // Execute `rustlings hint primitive_types3` for hints! 4 | 5 | fn main() { 6 | let a = [1; 100]; 7 | 8 | if a.len() >= 100 { 9 | println!("Wow, that's a big array!"); 10 | } else { 11 | println!("Meh, I eat arrays like that for breakfast."); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/primitive_types/primitive_types4.rs: -------------------------------------------------------------------------------- 1 | // primitive_types4.rs 2 | // Get a slice out of Array a where the ??? is so that the test passes. 3 | // Execute `rustlings hint primitive_types4` for hints!! 4 | 5 | #[test] 6 | fn slice_out_of_array() { 7 | let a = [1, 2, 3, 4, 5]; 8 | 9 | let nice_slice = &a[1..4]; 10 | 11 | assert_eq!([2, 3, 4], nice_slice) 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/primitive_types/primitive_types5.rs: -------------------------------------------------------------------------------- 1 | // primitive_types5.rs 2 | // Destructure the `cat` tuple so that the println will work. 3 | // Execute `rustlings hint primitive_types5` for hints! 4 | 5 | fn main() { 6 | let cat = ("Furry McFurson", 3.5); 7 | let (name, age) = cat; 8 | 9 | println!("{} is {} years old.", name, age); 10 | } 11 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/primitive_types/primitive_types6.rs: -------------------------------------------------------------------------------- 1 | // primitive_types6.rs 2 | // Use a tuple index to access the second element of `numbers`. 3 | // You can put the expression for the second element where ??? is so that the test passes. 4 | // Execute `rustlings hint primitive_types6` for hints! 5 | 6 | #[test] 7 | fn indexing_tuple() { 8 | let numbers = (1, 2, 3); 9 | // Replace below ??? with the tuple indexing syntax. 10 | let second = numbers.1; 11 | 12 | assert_eq!(2, second, "This is not the 2nd number in the tuple!") 13 | } 14 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/quiz1.rs: -------------------------------------------------------------------------------- 1 | // quiz1.rs 2 | // This is a quiz for the following sections: 3 | // - Variables 4 | // - Functions 5 | 6 | // Mary is buying apples. One apple usually costs 2 Rustbucks, but if you buy 7 | // more than 40 at once, each apple only costs 1! Write a function that calculates 8 | // the price of an order of apples given the order amount. No hints this time! 9 | 10 | // Put your function here! 11 | // fn ..... { 12 | fn calculate_apple_price(quantity: u32) -> u32 { 13 | if quantity > 40 { 14 | quantity 15 | } else { 16 | quantity * 2 17 | } 18 | } 19 | 20 | // Don't modify this function! 21 | #[test] 22 | fn verify_test() { 23 | let price1 = calculate_apple_price(35); 24 | let price2 = calculate_apple_price(65); 25 | 26 | assert_eq!(70, price1); 27 | assert_eq!(65, price2); 28 | } 29 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/quiz3.rs: -------------------------------------------------------------------------------- 1 | // quiz3.rs 2 | // This is a quiz for the following sections: 3 | // - Tests 4 | 5 | // This quiz isn't testing our function -- make it do that in such a way that 6 | // the test passes. Then write a second test that tests that we get the result 7 | // we expect to get when we call `times_two` with a negative number. 8 | // No hints, you can do this :) 9 | 10 | pub fn times_two(num: i32) -> i32 { 11 | num * 2 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | 18 | #[test] 19 | fn returns_twice_of_positive_numbers() { 20 | assert_eq!(times_two(4), 8); 21 | } 22 | 23 | #[test] 24 | fn returns_twice_of_negative_numbers() { 25 | assert_eq!(times_two(-4), -8); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/quiz4.rs: -------------------------------------------------------------------------------- 1 | // quiz4.rs 2 | // This quiz covers the sections: 3 | // - Modules 4 | // - Macros 5 | 6 | // Write a macro that passes the quiz! No hints this time, you can do it! 7 | macro_rules! my_macro { 8 | ($val:expr) => { 9 | format!("Hello {}", $val) 10 | }; 11 | } 12 | 13 | #[cfg(test)] 14 | mod tests { 15 | use super::*; 16 | 17 | #[test] 18 | fn test_my_macro_world() { 19 | assert_eq!(my_macro!("world!"), "Hello world!"); 20 | } 21 | 22 | #[test] 23 | fn test_my_macro_goodbye() { 24 | assert_eq!(my_macro!("goodbye!"), "Hello goodbye!"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/standard_library_types/README.md: -------------------------------------------------------------------------------- 1 | # Standard library types 2 | 3 | This section will teach you about Box, Shared-State Concurrency and Iterators. 4 | 5 | ## Further information 6 | 7 | - [Using Box to Point to Data on the Heap](https://doc.rust-lang.org/book/ch15-01-box.html) 8 | - [Shared-State Concurrency](https://doc.rust-lang.org/book/ch16-03-shared-state.html) 9 | - [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html) 10 | - [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/) 11 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/standard_library_types/iterators4.rs: -------------------------------------------------------------------------------- 1 | // iterators4.rs 2 | 3 | pub fn factorial(num: u64) -> u64 { 4 | // Complete this function to return the factorial of num 5 | // Do not use: 6 | // - return 7 | // Try not to use: 8 | // - imperative style loops (for, while) 9 | // - additional variables 10 | // For an extra challenge, don't use: 11 | // - recursion 12 | // Execute `rustlings hint iterators4` for hints. 13 | (1..=num).fold(1, |acc, v| acc * v) 14 | } 15 | 16 | #[cfg(test)] 17 | mod tests { 18 | use super::*; 19 | 20 | #[test] 21 | fn factorial_of_1() { 22 | assert_eq!(1, factorial(1)); 23 | } 24 | #[test] 25 | fn factorial_of_2() { 26 | assert_eq!(2, factorial(2)); 27 | } 28 | 29 | #[test] 30 | fn factorial_of_4() { 31 | assert_eq!(24, factorial(4)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/strings/README.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | Rust has two string types, a string slice (`&str`) and an owned string (`String`). 4 | We're not going to dictate when you should use which one, but we'll show you how 5 | to identify and create them, as well as use them. 6 | 7 | ## Further information 8 | 9 | - [Strings](https://doc.rust-lang.org/book/ch08-02-strings.html) 10 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/strings/strings1.rs: -------------------------------------------------------------------------------- 1 | // strings1.rs 2 | // Make me compile without changing the function signature! 3 | // Execute `rustlings hint strings1` for hints ;) 4 | 5 | fn main() { 6 | let answer = current_favorite_color(); 7 | println!("My current favorite color is {}", answer); 8 | } 9 | 10 | fn current_favorite_color() -> String { 11 | "blue".to_string() 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/strings/strings2.rs: -------------------------------------------------------------------------------- 1 | // strings2.rs 2 | // Make me compile without changing the function signature! 3 | // Execute `rustlings hint strings2` for hints :) 4 | 5 | fn main() { 6 | let word = String::from("green"); // Try not changing this line :) 7 | if is_a_color_word(&word) { 8 | println!("That is a color word I know!"); 9 | } else { 10 | println!("That is not a color word I know."); 11 | } 12 | } 13 | 14 | fn is_a_color_word(attempt: &str) -> bool { 15 | attempt == "green" || attempt == "blue" || attempt == "red" 16 | } 17 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/structs/README.md: -------------------------------------------------------------------------------- 1 | # Structs 2 | 3 | Rust has three struct types: a classic C struct, a tuple struct, and a unit struct. 4 | 5 | ## Further information 6 | 7 | - [Structures](https://doc.rust-lang.org/book/ch05-01-defining-structs.html) 8 | - [Method Syntax](https://doc.rust-lang.org/book/ch05-03-method-syntax.html) 9 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/tests/README.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | Going out of order from the book to cover tests -- many of the following exercises will ask you to make tests pass! 4 | 5 | ## Further information 6 | 7 | - [Writing Tests](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) 8 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/tests/tests1.rs: -------------------------------------------------------------------------------- 1 | // tests1.rs 2 | // Tests are important to ensure that your code does what you think it should do. 3 | // Tests can be run on this file with the following command: 4 | // rustlings run tests1 5 | 6 | // This test has a problem with it -- make the test compile! Make the test 7 | // pass! Make the test fail! Execute `rustlings hint tests1` for hints :) 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | #[test] 12 | fn you_can_assert() { 13 | assert!(true); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/tests/tests2.rs: -------------------------------------------------------------------------------- 1 | // tests2.rs 2 | // This test has a problem with it -- make the test compile! Make the test 3 | // pass! Make the test fail! Execute `rustlings hint tests2` for hints :) 4 | 5 | #[cfg(test)] 6 | mod tests { 7 | #[test] 8 | fn you_can_assert_eq() { 9 | assert_eq!(true, true); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/tests/tests3.rs: -------------------------------------------------------------------------------- 1 | // tests3.rs 2 | // This test isn't testing our function -- make it do that in such a way that 3 | // the test passes. Then write a second test that tests whether we get the result 4 | // we expect to get when we call `is_even(5)`. 5 | // Execute `rustlings hint tests3` for hints :) 6 | 7 | pub fn is_even(num: i32) -> bool { 8 | num % 2 == 0 9 | } 10 | 11 | #[cfg(test)] 12 | mod tests { 13 | use super::*; 14 | 15 | #[test] 16 | fn is_true_when_even() { 17 | assert!(is_even(2)); 18 | } 19 | 20 | #[test] 21 | fn is_false_when_odd() { 22 | assert!(is_even(1) == false); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/threads/README.md: -------------------------------------------------------------------------------- 1 | # Threads 2 | 3 | In most current operating systems, an executed program’s code is run in a process, and the operating system manages multiple processes at once. 4 | Within your program, you can also have independent parts that run simultaneously. The features that run these independent parts are called threads. 5 | 6 | ## Further information 7 | 8 | - [Dining Philosophers example](https://doc.rust-lang.org/1.4.0/book/dining-philosophers.html) 9 | - [Using Threads to Run Code Simultaneously](https://doc.rust-lang.org/book/ch16-01-threads.html) 10 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/traits/README.md: -------------------------------------------------------------------------------- 1 | # Traits 2 | 3 | A trait is a collection of methods. 4 | 5 | Data types can implement traits. To do so, the methods making up the trait are defined for the data type. For example, the `String` data type implements the `From<&str>` trait. This allows a user to write `String::from("hello")`. 6 | 7 | In this way, traits are somewhat similar to Java interfaces and C++ abstract classes. 8 | 9 | Some additional common Rust traits include: 10 | - `Clone` (the `clone` method) 11 | - `Display` (which allows formatted display via `{}`) 12 | - `Debug` (which allows formatted display via `{:?}`) 13 | 14 | Because traits indicate shared behavior between data types, they are useful when writing generics. 15 | 16 | 17 | ## Further information 18 | 19 | - [Traits](https://doc.rust-lang.org/book/ch10-02-traits.html) 20 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/variables/README.md: -------------------------------------------------------------------------------- 1 | # Variables 2 | 3 | In Rust, variables are immutable by default. 4 | When a variable is immutable, once a value is bound to a name, you can’t change that value. 5 | You can make them mutable by adding mut in front of the variable name. 6 | 7 | ## Further information 8 | 9 | - [Variables and Mutability](https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html) 10 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/variables/variables1.rs: -------------------------------------------------------------------------------- 1 | // variables1.rs 2 | // Make me compile! Execute the command `rustlings hint variables1` if you want a hint :) 3 | 4 | // About this `I AM NOT DONE` thing: 5 | // We sometimes encourage you to keep trying things on a given exercise, 6 | // even after you already figured it out. If you got everything working and 7 | // feel ready for the next exercise, remove the `I AM NOT DONE` comment below. 8 | 9 | fn main() { 10 | let x = 5; 11 | println!("x has the value {}", x); 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/variables/variables2.rs: -------------------------------------------------------------------------------- 1 | // variables2.rs 2 | // Make me compile! Execute the command `rustlings hint variables2` if you want a hint :) 3 | 4 | fn main() { 5 | let x = 10; 6 | if x == 10 { 7 | println!("Ten!"); 8 | } else { 9 | println!("Not ten!"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/variables/variables3.rs: -------------------------------------------------------------------------------- 1 | // variables3.rs 2 | // Make me compile! Execute the command `rustlings hint variables3` if you want a hint :) 3 | 4 | fn main() { 5 | let mut x = 3; 6 | println!("Number {}", x); 7 | x = 5; // don't change this line 8 | println!("Number {}", x); 9 | } 10 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/variables/variables4.rs: -------------------------------------------------------------------------------- 1 | // variables4.rs 2 | // Make me compile! Execute the command `rustlings hint variables4` if you want a hint :) 3 | 4 | fn main() { 5 | let x: i32 = 20; 6 | println!("Number {}", x); 7 | } 8 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/variables/variables5.rs: -------------------------------------------------------------------------------- 1 | // variables5.rs 2 | // Make me compile! Execute the command `rustlings hint variables5` if you want a hint :) 3 | 4 | fn main() { 5 | let number = "T-H-R-E-E"; 6 | println!("Spell a Number : {}", number); 7 | let number = 3; 8 | println!("Number plus two is : {}", number + 2); 9 | } 10 | -------------------------------------------------------------------------------- /examples/rustlings/exercises/variables/variables6.rs: -------------------------------------------------------------------------------- 1 | // variables6.rs 2 | // Make me compile! Execute the command `rustlings hint variables6` if you want a hint :) 3 | 4 | const NUMBER: i32 = 3; 5 | fn main() { 6 | println!("Number {}", NUMBER); 7 | } 8 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/failure/compFailure.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let 3 | } -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/failure/compNoExercise.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | } 3 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/failure/info.toml: -------------------------------------------------------------------------------- 1 | [[exercises]] 2 | name = "compFailure" 3 | path = "compFailure.rs" 4 | mode = "compile" 5 | hint = "" 6 | 7 | [[exercises]] 8 | name = "testFailure" 9 | path = "testFailure.rs" 10 | mode = "test" 11 | hint = "Hello!" 12 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/failure/testFailure.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn passing() { 3 | asset!(true); 4 | } 5 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/failure/testNotPassed.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn not_passing() { 3 | assert!(false); 4 | } 5 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/state/finished_exercise.rs: -------------------------------------------------------------------------------- 1 | // fake_exercise 2 | 3 | fn main() { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/state/info.toml: -------------------------------------------------------------------------------- 1 | [[exercises]] 2 | name = "pending_exercise" 3 | path = "pending_exercise.rs" 4 | mode = "compile" 5 | hint = """""" 6 | 7 | [[exercises]] 8 | name = "pending_test_exercise" 9 | path = "pending_test_exercise.rs" 10 | mode = "test" 11 | hint = """""" 12 | 13 | [[exercises]] 14 | name = "finished_exercise" 15 | path = "finished_exercise.rs" 16 | mode = "compile" 17 | hint = """""" 18 | 19 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/state/pending_exercise.rs: -------------------------------------------------------------------------------- 1 | // fake_exercise 2 | 3 | // I AM NOT DONE 4 | 5 | fn main() { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/state/pending_test_exercise.rs: -------------------------------------------------------------------------------- 1 | // I AM NOT DONE 2 | 3 | #[test] 4 | fn it_works() {} 5 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/success/compSuccess.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | } 3 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/success/info.toml: -------------------------------------------------------------------------------- 1 | [[exercises]] 2 | name = "compSuccess" 3 | path = "compSuccess.rs" 4 | mode = "compile" 5 | hint = """""" 6 | 7 | [[exercises]] 8 | name = "testSuccess" 9 | path = "testSuccess.rs" 10 | mode = "test" 11 | hint = """""" 12 | -------------------------------------------------------------------------------- /examples/rustlings/tests/fixture/success/testSuccess.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn passing() { 3 | println!("THIS TEST TOO SHALL PASS"); 4 | assert!(true); 5 | } 6 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | imports_granularity = "Module" 2 | match_block_trailing_comma = true 3 | group_imports = "StdExternalCrate" 4 | reorder_impl_items = true 5 | hard_tabs = true 6 | max_width = 120 7 | --------------------------------------------------------------------------------