diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index d0821b987c1..e7191fd8966 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -9175,39 +9175,6 @@ OwnPtr Parser::convert_to_calculation_node(CalcParsing::Node co return NegateCalculationNode::create(child_as_node.release_nonnull()); return nullptr; }, - [](Number const& number) -> OwnPtr { - return NumericCalculationNode::create(number); - }, - [this](Dimension const& dimension) -> OwnPtr { - if (dimension.is_angle()) - return NumericCalculationNode::create(dimension.angle()); - if (dimension.is_frequency()) - return NumericCalculationNode::create(dimension.frequency()); - if (dimension.is_length()) - return NumericCalculationNode::create(dimension.length()); - if (dimension.is_percentage()) { - // FIXME: Figure this out in non-property contexts - auto percentage_resolved_type = property_resolves_percentages_relative_to(m_context.current_property_id()); - return NumericCalculationNode::create(dimension.percentage(), percentage_resolved_type); - } - if (dimension.is_resolution()) - return NumericCalculationNode::create(dimension.resolution()); - if (dimension.is_time()) - return NumericCalculationNode::create(dimension.time()); - if (dimension.is_flex()) { - // https://www.w3.org/TR/css3-grid-layout/#fr-unit - // NOTE: values are not s (nor are they compatible with s, like some values), - // so they cannot be represented in or combined with other unit types in calc() expressions. - // FIXME: Flex is allowed in calc(), so figure out what this spec text means and how to implement it. - dbgln_if(CSS_PARSER_DEBUG, "Rejecting in calc()"); - return nullptr; - } - dbgln_if(CSS_PARSER_DEBUG, "Unrecognized dimension type in calc() expression: {}", dimension.to_string()); - return nullptr; - }, - [](CalculationNode::ConstantType const& constant_type) -> OwnPtr { - return ConstantCalculationNode::create(constant_type); - }, [this](NonnullRawPtr const& component_value) -> OwnPtr { // NOTE: This is the "process the leaf nodes" part of step 5 of https://drafts.csswg.org/css-values-4/#parse-a-calculation // We divert a little from the spec: Rather than modify an existing tree of values, we construct a new one from that source tree. @@ -9233,6 +9200,56 @@ OwnPtr Parser::convert_to_calculation_node(CalcParsing::Node co return leaf_calculation.release_nonnull(); } + // AD-HOC: We also need to convert tokens into their numeric types. + + if (component_value->is(Token::Type::Ident)) { + auto maybe_constant = CalculationNode::constant_type_from_string(component_value->token().ident()); + if (!maybe_constant.has_value()) + return nullptr; + return ConstantCalculationNode::create(*maybe_constant); + } + + if (component_value->is(Token::Type::Number)) + return NumericCalculationNode::create(component_value->token().number()); + + if (component_value->is(Token::Type::Dimension)) { + auto numeric_value = component_value->token().dimension_value(); + auto unit_string = component_value->token().dimension_unit(); + + if (auto length_type = Length::unit_from_name(unit_string); length_type.has_value()) + return NumericCalculationNode::create(Length { numeric_value, length_type.release_value() }); + + if (auto angle_type = Angle::unit_from_name(unit_string); angle_type.has_value()) + return NumericCalculationNode::create(Angle { numeric_value, angle_type.release_value() }); + + if (auto flex_type = Flex::unit_from_name(unit_string); flex_type.has_value()) { + // https://www.w3.org/TR/css3-grid-layout/#fr-unit + // NOTE: values are not s (nor are they compatible with s, like some values), + // so they cannot be represented in or combined with other unit types in calc() expressions. + // FIXME: Flex is allowed in calc(), so figure out what this spec text means and how to implement it. + dbgln_if(CSS_PARSER_DEBUG, "Rejecting in calc()"); + return nullptr; + } + + if (auto frequency_type = Frequency::unit_from_name(unit_string); frequency_type.has_value()) + return NumericCalculationNode::create(Frequency { numeric_value, frequency_type.release_value() }); + + if (auto resolution_type = Resolution::unit_from_name(unit_string); resolution_type.has_value()) + return NumericCalculationNode::create(Resolution { numeric_value, resolution_type.release_value() }); + + if (auto time_type = Time::unit_from_name(unit_string); time_type.has_value()) + return NumericCalculationNode::create(Time { numeric_value, time_type.release_value() }); + + dbgln_if(CSS_PARSER_DEBUG, "Unrecognized dimension type in calc() expression: {}", component_value->to_string()); + return nullptr; + } + + if (component_value->is(Token::Type::Percentage)) { + // FIXME: Figure this out in non-property contexts + auto percentage_resolved_type = property_resolves_percentages_relative_to(m_context.current_property_id()); + return NumericCalculationNode::create(Percentage { component_value->token().percentage() }, percentage_resolved_type); + } + // NOTE: If we get here, then we have a ComponentValue that didn't get replaced with something else, // so the calc() is invalid. dbgln_if(CSS_PARSER_DEBUG, "Leftover ComponentValue in calc tree! That probably means the syntax is invalid, but maybe we just didn't implement `{}` yet.", component_value->to_debug_string()); @@ -9265,24 +9282,6 @@ OwnPtr Parser::parse_a_calculation(Vector const } } - if (value.is(Token::Type::Ident)) { - auto maybe_constant = CalculationNode::constant_type_from_string(value.token().ident()); - if (maybe_constant.has_value()) { - values.append(maybe_constant.value()); - continue; - } - } - - if (value.is(Token::Type::Number)) { - values.append(value.token().number()); - continue; - } - - if (auto dimension = parse_dimension(value); dimension.has_value()) { - values.append(dimension.release_value()); - continue; - } - values.append(NonnullRawPtr { value }); } diff --git a/Libraries/LibWeb/CSS/Parser/Parser.h b/Libraries/LibWeb/CSS/Parser/Parser.h index 95b2439644f..358e9836d79 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Libraries/LibWeb/CSS/Parser/Parser.h @@ -43,7 +43,7 @@ struct ProductNode; struct SumNode; struct InvertNode; struct NegateNode; -using Node = Variant, NonnullOwnPtr, NonnullOwnPtr, NonnullOwnPtr, NonnullRawPtr>; +using Node = Variant, NonnullOwnPtr, NonnullOwnPtr, NonnullOwnPtr, NonnullRawPtr>; struct ProductNode { Vector children; };