diff --git a/Libraries/LibHTML/CSS/PropertyID.h b/Libraries/LibHTML/CSS/PropertyID.h new file mode 100644 index 0000000000..6e2be9e091 --- /dev/null +++ b/Libraries/LibHTML/CSS/PropertyID.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +namespace CSS { +enum class PropertyID { + Invalid, + + BackgroundColor, + BorderBottomColor, + BorderBottomStyle, + BorderBottomWidth, + BorderCollapse, + BorderLeftColor, + BorderLeftStyle, + BorderLeftWidth, + BorderRightColor, + BorderRightStyle, + BorderRightWidth, + BorderSpacing, + BorderTopColor, + BorderTopStyle, + BorderTopWidth, + Color, + Display, + FontFamily, + FontSize, + FontStyle, + FontVariant, + FontWeight, + Height, + LetterSpacing, + LineHeight, + ListStyle, + ListStyleImage, + ListStylePosition, + ListStyleType, + MarginBottom, + MarginLeft, + MarginRight, + MarginTop, + PaddingBottom, + PaddingLeft, + PaddingRight, + PaddingTop, + TextAlign, + TextDecoration, + TextIndent, + TextTransform, + Visibility, + WhiteSpace, + Width, + WordSpacing, +}; +} + +namespace AK { +template<> +struct Traits : public GenericTraits { + static unsigned hash(CSS::PropertyID property_id) { return int_hash((unsigned)property_id); } +}; +} diff --git a/Libraries/LibHTML/CSS/StyleDeclaration.h b/Libraries/LibHTML/CSS/StyleDeclaration.h index 9dd6c70509..55620b1516 100644 --- a/Libraries/LibHTML/CSS/StyleDeclaration.h +++ b/Libraries/LibHTML/CSS/StyleDeclaration.h @@ -4,7 +4,7 @@ #include struct StyleProperty { - String name; + CSS::PropertyID property_id; NonnullRefPtr value; bool important { false }; }; diff --git a/Libraries/LibHTML/CSS/StyleProperties.cpp b/Libraries/LibHTML/CSS/StyleProperties.cpp index d397853491..2c74171e28 100644 --- a/Libraries/LibHTML/CSS/StyleProperties.cpp +++ b/Libraries/LibHTML/CSS/StyleProperties.cpp @@ -2,38 +2,38 @@ #include #include -void StyleProperties::set_property(const String& name, NonnullRefPtr value) +void StyleProperties::set_property(CSS::PropertyID id, NonnullRefPtr value) { - m_property_values.set(name, move(value)); + m_property_values.set((unsigned)id, move(value)); } -Optional> StyleProperties::property(const String& name) const +Optional> StyleProperties::property(CSS::PropertyID id) const { - auto it = m_property_values.find(name); + auto it = m_property_values.find((unsigned)id); if (it == m_property_values.end()) return {}; return it->value; } -Length StyleProperties::length_or_fallback(const StringView& property_name, const Length& fallback) const +Length StyleProperties::length_or_fallback(CSS::PropertyID id, const Length& fallback) const { - auto value = property(property_name); + auto value = property(id); if (!value.has_value()) return fallback; return value.value()->to_length(); } -String StyleProperties::string_or_fallback(const StringView& property_name, const StringView& fallback) const +String StyleProperties::string_or_fallback(CSS::PropertyID id, const StringView& fallback) const { - auto value = property(property_name); + auto value = property(id); if (!value.has_value()) return fallback; return value.value()->to_string(); } -Color StyleProperties::color_or_fallback(const StringView& property_name, const Document& document, Color fallback) const +Color StyleProperties::color_or_fallback(CSS::PropertyID id, const Document& document, Color fallback) const { - auto value = property(property_name); + auto value = property(id); if (!value.has_value()) return fallback; return value.value()->to_color(document); @@ -41,8 +41,8 @@ Color StyleProperties::color_or_fallback(const StringView& property_name, const void StyleProperties::load_font() const { - auto font_family = string_or_fallback("font-family", "Katica"); - auto font_weight = string_or_fallback("font-weight", "normal"); + auto font_family = string_or_fallback(CSS::PropertyID::FontFamily, "Katica"); + auto font_weight = string_or_fallback(CSS::PropertyID::FontWeight, "normal"); String weight; if (font_weight == "lighter") diff --git a/Libraries/LibHTML/CSS/StyleProperties.h b/Libraries/LibHTML/CSS/StyleProperties.h index 4a551a8c5f..650836eed1 100644 --- a/Libraries/LibHTML/CSS/StyleProperties.h +++ b/Libraries/LibHTML/CSS/StyleProperties.h @@ -15,15 +15,15 @@ public: inline void for_each_property(Callback callback) const { for (auto& it : m_property_values) - callback(it.key, *it.value); + callback((CSS::PropertyID)it.key, *it.value); } - void set_property(const String& name, NonnullRefPtr value); - Optional> property(const String& name) const; + void set_property(CSS::PropertyID, NonnullRefPtr value); + Optional> property(CSS::PropertyID) const; - Length length_or_fallback(const StringView& property_name, const Length& fallback) const; - String string_or_fallback(const StringView& property_name, const StringView& fallback) const; - Color color_or_fallback(const StringView& property_name, const Document&, Color fallback) const; + Length length_or_fallback(CSS::PropertyID, const Length& fallback) const; + String string_or_fallback(CSS::PropertyID, const StringView& fallback) const; + Color color_or_fallback(CSS::PropertyID, const Document&, Color fallback) const; const Font& font() const { @@ -33,7 +33,7 @@ public: } private: - HashMap> m_property_values; + HashMap> m_property_values; void load_font() const; diff --git a/Libraries/LibHTML/CSS/StyleResolver.cpp b/Libraries/LibHTML/CSS/StyleResolver.cpp index 1745084414..76c4a34ae0 100644 --- a/Libraries/LibHTML/CSS/StyleResolver.cpp +++ b/Libraries/LibHTML/CSS/StyleResolver.cpp @@ -61,37 +61,36 @@ NonnullRefPtrVector StyleResolver::collect_matching_rules(const Eleme return matching_rules; } -bool StyleResolver::is_inherited_property(const StringView& name) +bool StyleResolver::is_inherited_property(CSS::PropertyID property_id) { - static HashTable inherited_properties; + static HashTable inherited_properties; if (inherited_properties.is_empty()) { - inherited_properties.set("border-collapse"); - inherited_properties.set("border-spacing"); - inherited_properties.set("color"); - inherited_properties.set("font-family"); - inherited_properties.set("font-size"); - inherited_properties.set("font-style"); - inherited_properties.set("font-variant"); - inherited_properties.set("font-weight"); - inherited_properties.set("font"); - inherited_properties.set("letter-spacing"); - inherited_properties.set("line-height"); - inherited_properties.set("list-style-image"); - inherited_properties.set("list-style-position"); - inherited_properties.set("list-style-type"); - inherited_properties.set("list-style"); - inherited_properties.set("text-align"); - inherited_properties.set("text-indent"); - inherited_properties.set("text-transform"); - inherited_properties.set("visibility"); - inherited_properties.set("white-space"); - inherited_properties.set("word-spacing"); + inherited_properties.set(CSS::PropertyID::BorderCollapse); + inherited_properties.set(CSS::PropertyID::BorderSpacing); + inherited_properties.set(CSS::PropertyID::Color); + inherited_properties.set(CSS::PropertyID::FontFamily); + inherited_properties.set(CSS::PropertyID::FontSize); + inherited_properties.set(CSS::PropertyID::FontStyle); + inherited_properties.set(CSS::PropertyID::FontVariant); + inherited_properties.set(CSS::PropertyID::FontWeight); + inherited_properties.set(CSS::PropertyID::LetterSpacing); + inherited_properties.set(CSS::PropertyID::LineHeight); + inherited_properties.set(CSS::PropertyID::ListStyle); + inherited_properties.set(CSS::PropertyID::ListStyleImage); + inherited_properties.set(CSS::PropertyID::ListStylePosition); + inherited_properties.set(CSS::PropertyID::ListStyleType); + inherited_properties.set(CSS::PropertyID::TextAlign); + inherited_properties.set(CSS::PropertyID::TextIndent); + inherited_properties.set(CSS::PropertyID::TextTransform); + inherited_properties.set(CSS::PropertyID::Visibility); + inherited_properties.set(CSS::PropertyID::WhiteSpace); + inherited_properties.set(CSS::PropertyID::WordSpacing); // FIXME: This property is not supposed to be inherited, but we currently // rely on inheritance to propagate decorations into line boxes. - inherited_properties.set("text-decoration"); + inherited_properties.set(CSS::PropertyID::TextDecoration); } - return inherited_properties.contains(name); + return inherited_properties.contains(property_id); } NonnullRefPtr StyleResolver::resolve_style(const Element& element, const StyleProperties* parent_style) const @@ -99,9 +98,9 @@ NonnullRefPtr StyleResolver::resolve_style(const Element& eleme auto style = StyleProperties::create(); if (parent_style) { - parent_style->for_each_property([&](const StringView& name, auto& value) { - if (is_inherited_property(name)) - style->set_property(name, value); + parent_style->for_each_property([&](auto property_id, auto& value) { + if (is_inherited_property(property_id)) + style->set_property(property_id, value); }); } @@ -110,7 +109,7 @@ NonnullRefPtr StyleResolver::resolve_style(const Element& eleme auto matching_rules = collect_matching_rules(element); for (auto& rule : matching_rules) { for (auto& property : rule.declaration().properties()) { - style->set_property(property.name, property.value); + style->set_property(property.property_id, property.value); } } @@ -118,7 +117,7 @@ NonnullRefPtr StyleResolver::resolve_style(const Element& eleme if (!style_attribute.is_null()) { if (auto declaration = parse_css_declaration(style_attribute)) { for (auto& property : declaration->properties()) { - style->set_property(property.name, property.value); + style->set_property(property.property_id, property.value); } } } diff --git a/Libraries/LibHTML/CSS/StyleResolver.h b/Libraries/LibHTML/CSS/StyleResolver.h index fd0a358374..49d59704f0 100644 --- a/Libraries/LibHTML/CSS/StyleResolver.h +++ b/Libraries/LibHTML/CSS/StyleResolver.h @@ -22,7 +22,7 @@ public: NonnullRefPtrVector collect_matching_rules(const Element&) const; - static bool is_inherited_property(const StringView&); + static bool is_inherited_property(CSS::PropertyID); private: template diff --git a/Libraries/LibHTML/CSS/StyleValue.h b/Libraries/LibHTML/CSS/StyleValue.h index 3a0f43e69b..1cfa3d1c3b 100644 --- a/Libraries/LibHTML/CSS/StyleValue.h +++ b/Libraries/LibHTML/CSS/StyleValue.h @@ -6,6 +6,7 @@ #include #include #include +#include class Document; diff --git a/Libraries/LibHTML/DOM/Document.cpp b/Libraries/LibHTML/DOM/Document.cpp index 4543c897ae..5d6d45a9d8 100644 --- a/Libraries/LibHTML/DOM/Document.cpp +++ b/Libraries/LibHTML/DOM/Document.cpp @@ -92,7 +92,7 @@ Color Document::background_color() const if (!body_layout_node) return Color::White; - auto background_color = body_layout_node->style().property("background-color"); + auto background_color = body_layout_node->style().property(CSS::PropertyID::BackgroundColor); if (!background_color.has_value() || !background_color.value()->is_color()) return Color::White; diff --git a/Libraries/LibHTML/DOM/Element.cpp b/Libraries/LibHTML/DOM/Element.cpp index 19dd68d121..5ef79e9986 100644 --- a/Libraries/LibHTML/DOM/Element.cpp +++ b/Libraries/LibHTML/DOM/Element.cpp @@ -73,7 +73,7 @@ RefPtr Element::create_layout_node(const StyleResolver& resolver, co { auto style = resolver.resolve_style(*this, parent_style); - auto display_property = style->property("display"); + auto display_property = style->property(CSS::PropertyID::Display); String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline"; if (display == "none") diff --git a/Libraries/LibHTML/DOM/HTMLBodyElement.cpp b/Libraries/LibHTML/DOM/HTMLBodyElement.cpp index 14a0b9b234..724bf31459 100644 --- a/Libraries/LibHTML/DOM/HTMLBodyElement.cpp +++ b/Libraries/LibHTML/DOM/HTMLBodyElement.cpp @@ -18,11 +18,11 @@ void HTMLBodyElement::apply_presentational_hints(StyleProperties& style) const if (name == "bgcolor") { auto color = Color::from_string(value); if (color.has_value()) - style.set_property("background-color", ColorStyleValue::create(color.value())); + style.set_property(CSS::PropertyID::BackgroundColor, ColorStyleValue::create(color.value())); } else if (name == "text") { auto color = Color::from_string(value); if (color.has_value()) - style.set_property("color", ColorStyleValue::create(color.value())); + style.set_property(CSS::PropertyID::Color, ColorStyleValue::create(color.value())); } }); } diff --git a/Libraries/LibHTML/DOM/HTMLFontElement.cpp b/Libraries/LibHTML/DOM/HTMLFontElement.cpp index 56ff2e8848..fca7ad0f04 100644 --- a/Libraries/LibHTML/DOM/HTMLFontElement.cpp +++ b/Libraries/LibHTML/DOM/HTMLFontElement.cpp @@ -17,7 +17,7 @@ void HTMLFontElement::apply_presentational_hints(StyleProperties& style) const if (name == "color") { auto color = Color::from_string(value); if (color.has_value()) - style.set_property("color", ColorStyleValue::create(color.value())); + style.set_property(CSS::PropertyID::Color, ColorStyleValue::create(color.value())); } }); } diff --git a/Libraries/LibHTML/DOM/HTMLImageElement.cpp b/Libraries/LibHTML/DOM/HTMLImageElement.cpp index 1210fe297e..846318fd20 100644 --- a/Libraries/LibHTML/DOM/HTMLImageElement.cpp +++ b/Libraries/LibHTML/DOM/HTMLImageElement.cpp @@ -59,7 +59,7 @@ RefPtr HTMLImageElement::create_layout_node(const StyleResolver& res { auto style = resolver.resolve_style(*this, parent_style); - auto display_property = style->property("display"); + auto display_property = style->property(CSS::PropertyID::Display); String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline"; if (display == "none") diff --git a/Libraries/LibHTML/Dump.cpp b/Libraries/LibHTML/Dump.cpp index 62619de074..82458f44b0 100644 --- a/Libraries/LibHTML/Dump.cpp +++ b/Libraries/LibHTML/Dump.cpp @@ -114,10 +114,10 @@ void dump_tree(const LayoutNode& layout_node) } } - layout_node.style().for_each_property([&](auto& key, auto& value) { + layout_node.style().for_each_property([&](auto property_id, auto& value) { for (int i = 0; i < indent; ++i) dbgprintf(" "); - dbgprintf(" (%s: %s)\n", key.characters(), value.to_string().characters()); + dbgprintf(" (CSS::PropertyID(%u): %s)\n", (unsigned)property_id, value.to_string().characters()); }); ++indent; @@ -170,7 +170,7 @@ void dump_rule(const StyleRule& rule) } dbgprintf(" Declarations:\n"); for (auto& property : rule.declaration().properties()) { - dbgprintf(" '%s': '%s'\n", property.name.characters(), property.value->to_string().characters()); + dbgprintf(" CSS::PropertyID(%u): '%s'\n", (unsigned)property.property_id, property.value->to_string().characters()); } } diff --git a/Libraries/LibHTML/Layout/LayoutBlock.cpp b/Libraries/LibHTML/Layout/LayoutBlock.cpp index a4db9dbdf3..3f3e95c625 100644 --- a/Libraries/LibHTML/Layout/LayoutBlock.cpp +++ b/Libraries/LibHTML/Layout/LayoutBlock.cpp @@ -83,13 +83,13 @@ void LayoutBlock::compute_width() auto auto_value = Length(); auto zero_value = Length(0, Length::Type::Absolute); - auto width = style.length_or_fallback("width", auto_value); - auto margin_left = style.length_or_fallback("margin-left", zero_value); - auto margin_right = style.length_or_fallback("margin-right", zero_value); - auto border_left = style.length_or_fallback("border-left", zero_value); - auto border_right = style.length_or_fallback("border-right", zero_value); - auto padding_left = style.length_or_fallback("padding-left", zero_value); - auto padding_right = style.length_or_fallback("padding-right", zero_value); + auto width = style.length_or_fallback(CSS::PropertyID::Width, auto_value); + auto margin_left = style.length_or_fallback(CSS::PropertyID::MarginLeft, zero_value); + auto margin_right = style.length_or_fallback(CSS::PropertyID::MarginRight, zero_value); + auto border_left = style.length_or_fallback(CSS::PropertyID::BorderLeftWidth, zero_value); + auto border_right = style.length_or_fallback(CSS::PropertyID::BorderRightWidth, zero_value); + auto padding_left = style.length_or_fallback(CSS::PropertyID::PaddingLeft, zero_value); + auto padding_right = style.length_or_fallback(CSS::PropertyID::PaddingRight, zero_value); #ifdef HTML_DEBUG dbg() << " Left: " << margin_left << "+" << border_left << "+" << padding_left; @@ -158,14 +158,14 @@ void LayoutBlock::compute_position() auto auto_value = Length(); auto zero_value = Length(0, Length::Type::Absolute); - auto width = style.length_or_fallback("width", auto_value); + auto width = style.length_or_fallback(CSS::PropertyID::Width, auto_value); - box_model().margin().top = style.length_or_fallback("margin-top", zero_value); - box_model().margin().bottom = style.length_or_fallback("margin-bottom", zero_value); - box_model().border().top = style.length_or_fallback("border-top", zero_value); - box_model().border().bottom = style.length_or_fallback("border-bottom", zero_value); - box_model().padding().top = style.length_or_fallback("padding-top", zero_value); - box_model().padding().bottom = style.length_or_fallback("padding-bottom", zero_value); + box_model().margin().top = style.length_or_fallback(CSS::PropertyID::MarginTop, zero_value); + box_model().margin().bottom = style.length_or_fallback(CSS::PropertyID::MarginBottom, zero_value); + box_model().border().top = style.length_or_fallback(CSS::PropertyID::BorderTopWidth, zero_value); + box_model().border().bottom = style.length_or_fallback(CSS::PropertyID::BorderBottomWidth, zero_value); + box_model().padding().top = style.length_or_fallback(CSS::PropertyID::PaddingTop, zero_value); + box_model().padding().bottom = style.length_or_fallback(CSS::PropertyID::PaddingBottom, zero_value); rect().set_x(containing_block()->rect().x() + box_model().margin().left.to_px() + box_model().border().left.to_px() + box_model().padding().left.to_px()); int top_border = -1; @@ -184,7 +184,7 @@ void LayoutBlock::compute_height() { auto& style = this->style(); - auto height_property = style.property("height"); + auto height_property = style.property(CSS::PropertyID::Height); if (!height_property.has_value()) return; auto height_length = height_property.value()->to_length(); @@ -197,7 +197,7 @@ void LayoutBlock::render(RenderingContext& context) LayoutNode::render(context); // FIXME: position this properly - if (style().string_or_fallback("display", "block") == "list-item") { + if (style().string_or_fallback(CSS::PropertyID::Display, "block") == "list-item") { Rect bullet_rect { rect().x() - 8, rect().y() + 4, @@ -205,7 +205,7 @@ void LayoutBlock::render(RenderingContext& context) 3 }; - context.painter().fill_rect(bullet_rect, style().color_or_fallback("color", document(), Color::Black)); + context.painter().fill_rect(bullet_rect, style().color_or_fallback(CSS::PropertyID::Color, document(), Color::Black)); } if (children_are_inline()) { @@ -242,9 +242,9 @@ NonnullRefPtr LayoutBlock::style_for_anonymous_block() const { auto new_style = StyleProperties::create(); - style().for_each_property([&](auto& name, auto& value) { - if (StyleResolver::is_inherited_property(name)) - new_style->set_property(name, value); + style().for_each_property([&](auto property_id, auto& value) { + if (StyleResolver::is_inherited_property(property_id)) + new_style->set_property(property_id, value); }); return new_style; diff --git a/Libraries/LibHTML/Layout/LayoutImage.cpp b/Libraries/LibHTML/Layout/LayoutImage.cpp index d81e2e7b6a..82a111c04a 100644 --- a/Libraries/LibHTML/Layout/LayoutImage.cpp +++ b/Libraries/LibHTML/Layout/LayoutImage.cpp @@ -40,7 +40,7 @@ void LayoutImage::render(RenderingContext& context) auto alt = node().alt(); if (alt.is_empty()) alt = node().src(); - context.painter().draw_text(rect(), alt, TextAlignment::Center, style().color_or_fallback("color", document(), Color::Black), TextElision::Right); + context.painter().draw_text(rect(), alt, TextAlignment::Center, style().color_or_fallback(CSS::PropertyID::Color, document(), Color::Black), TextElision::Right); } else { context.painter().draw_scaled_bitmap(rect(), *node().bitmap(), node().bitmap()->rect()); } diff --git a/Libraries/LibHTML/Layout/LayoutNode.cpp b/Libraries/LibHTML/Layout/LayoutNode.cpp index 3be9e7aca2..3527c3dbd1 100644 --- a/Libraries/LibHTML/Layout/LayoutNode.cpp +++ b/Libraries/LibHTML/Layout/LayoutNode.cpp @@ -52,14 +52,15 @@ void LayoutNode::render(RenderingContext& context) padded_rect.set_y(rect().y() - box_model().padding().top.to_px()); padded_rect.set_height(rect().height() + box_model().padding().top.to_px() + box_model().padding().bottom.to_px()); - auto bgcolor = style().property("background-color"); + auto bgcolor = style().property(CSS::PropertyID::BackgroundColor); if (bgcolor.has_value() && bgcolor.value()->is_color()) { context.painter().fill_rect(padded_rect, bgcolor.value()->to_color(document())); } - auto border_width_value = style().property("border-width"); - auto border_color_value = style().property("border-color"); - auto border_style_value = style().property("border-style"); + // FIXME: Respect all individual border sides + auto border_width_value = style().property(CSS::PropertyID::BorderTopWidth); + auto border_color_value = style().property(CSS::PropertyID::BorderTopColor); + auto border_style_value = style().property(CSS::PropertyID::BorderTopStyle); if (border_width_value.has_value() && border_color_value.has_value()) { int border_width = border_width_value.value()->to_length().to_px(); Color border_color = border_color_value.value()->to_color(document()); diff --git a/Libraries/LibHTML/Layout/LayoutText.cpp b/Libraries/LibHTML/Layout/LayoutText.cpp index a75b7f11e2..581760d11c 100644 --- a/Libraries/LibHTML/Layout/LayoutText.cpp +++ b/Libraries/LibHTML/Layout/LayoutText.cpp @@ -30,7 +30,7 @@ const String& LayoutText::text_for_style(const StyleProperties& style) const { static String one_space = " "; if (is_all_whitespace(node().data())) { - if (style.string_or_fallback("white-space", "normal") == "normal") + if (style.string_or_fallback(CSS::PropertyID::WhiteSpace, "normal") == "normal") return one_space; } return node().data(); @@ -41,8 +41,8 @@ void LayoutText::render_fragment(RenderingContext& context, const LineBoxFragmen auto& painter = context.painter(); painter.set_font(style().font()); - auto color = style().color_or_fallback("color", document(), Color::Black); - auto text_decoration = style().string_or_fallback("text-decoration", "none"); + auto color = style().color_or_fallback(CSS::PropertyID::Color, document(), Color::Black); + auto text_decoration = style().string_or_fallback(CSS::PropertyID::TextDecoration, "none"); bool is_underline = text_decoration == "underline"; if (is_underline) @@ -131,7 +131,7 @@ void LayoutText::split_into_lines(LayoutBlock& container) line_boxes.append(LineBox()); int available_width = container.rect().width() - line_boxes.last().width(); - bool is_preformatted = style().string_or_fallback("white-space", "normal") == "pre"; + bool is_preformatted = style().string_or_fallback(CSS::PropertyID::WhiteSpace, "normal") == "pre"; if (is_preformatted) { for_each_source_line([&](const Utf8View& view, int start, int length) { line_boxes.last().add_fragment(*this, start, length, font.width(view), line_height); diff --git a/Libraries/LibHTML/Parser/CSSParser.cpp b/Libraries/LibHTML/Parser/CSSParser.cpp index 7b43b046ac..4166177b78 100644 --- a/Libraries/LibHTML/Parser/CSSParser.cpp +++ b/Libraries/LibHTML/Parser/CSSParser.cpp @@ -1,13 +1,14 @@ +#include #include #include #include #include -#define PARSE_ASSERT(x) \ - if (!(x)) { \ - dbg() << "CSS PARSER ASSERTION FAILED: " << #x; \ +#define PARSE_ASSERT(x) \ + if (!(x)) { \ + dbg() << "CSS PARSER ASSERTION FAILED: " << #x; \ dbg() << "At character# " << index << " in CSS: _" << css << "_"; \ - ASSERT_NOT_REACHED(); \ + ASSERT_NOT_REACHED(); \ } static Optional parse_css_color(const StringView& view) @@ -47,6 +48,55 @@ NonnullRefPtr parse_css_value(const StringView& view) return StringStyleValue::create(string); } +static CSS::PropertyID parse_css_property_id(const StringView& string) +{ + static HashMap map; + if (map.is_empty()) { + map.set("background-color", CSS::PropertyID::BackgroundColor); + map.set("border-bottom-style", CSS::PropertyID::BorderBottomStyle); + map.set("border-bottom-width", CSS::PropertyID::BorderBottomWidth); + map.set("border-collapse", CSS::PropertyID::BorderCollapse); + map.set("border-left-style", CSS::PropertyID::BorderLeftStyle); + map.set("border-left-width", CSS::PropertyID::BorderLeftWidth); + map.set("border-right-style", CSS::PropertyID::BorderRightStyle); + map.set("border-right-width", CSS::PropertyID::BorderRightWidth); + map.set("border-spacing", CSS::PropertyID::BorderSpacing); + map.set("border-top-style", CSS::PropertyID::BorderTopStyle); + map.set("border-top-width", CSS::PropertyID::BorderTopWidth); + map.set("color", CSS::PropertyID::Color); + map.set("display", CSS::PropertyID::Display); + map.set("font-family", CSS::PropertyID::FontFamily); + map.set("font-size", CSS::PropertyID::FontSize); + map.set("font-style", CSS::PropertyID::FontStyle); + map.set("font-variant", CSS::PropertyID::FontVariant); + map.set("font-weight", CSS::PropertyID::FontWeight); + map.set("height", CSS::PropertyID::Height); + map.set("letter-spacing", CSS::PropertyID::LetterSpacing); + map.set("line-height", CSS::PropertyID::LineHeight); + map.set("list-style", CSS::PropertyID::ListStyle); + map.set("list-style-image", CSS::PropertyID::ListStyleImage); + map.set("list-style-position", CSS::PropertyID::ListStylePosition); + map.set("list-style-type", CSS::PropertyID::ListStyleType); + map.set("margin-bottom", CSS::PropertyID::MarginBottom); + map.set("margin-left", CSS::PropertyID::MarginLeft); + map.set("margin-right", CSS::PropertyID::MarginRight); + map.set("margin-top", CSS::PropertyID::MarginTop); + map.set("padding-bottom", CSS::PropertyID::PaddingBottom); + map.set("padding-left", CSS::PropertyID::PaddingLeft); + map.set("padding-right", CSS::PropertyID::PaddingRight); + map.set("padding-top", CSS::PropertyID::PaddingTop); + map.set("text-align", CSS::PropertyID::TextAlign); + map.set("text-decoration", CSS::PropertyID::TextDecoration); + map.set("text-indent", CSS::PropertyID::TextIndent); + map.set("text-transform", CSS::PropertyID::TextTransform); + map.set("visibility", CSS::PropertyID::Visibility); + map.set("white-space", CSS::PropertyID::WhiteSpace); + map.set("width", CSS::PropertyID::Width); + map.set("word-spacing", CSS::PropertyID::WordSpacing); + } + return map.get(string).value_or(CSS::PropertyID::Invalid); +} + class CSSParser { public: CSSParser(const StringView& input) @@ -233,7 +283,7 @@ public: if (peek() != '}') consume_specific(';'); - return StyleProperty { property_name, parse_css_value(property_value), is_important }; + return StyleProperty { parse_css_property_id(property_name), parse_css_value(property_value), is_important }; } void parse_declaration()