LibWeb: Parse CSS fit-content(<length-percentage>) values

Before this change, we only parsed fit-content as a standalone keyword,
but CSS-SIZING-3 added it as a function as well. I don't know of
anything else in CSS that is overloaded like this, so it ends up looking
a little awkward in the implementation.

Note that a lot of code had already been prepped for fit-content values
to have an argument, we just weren't parsing it.
This commit is contained in:
Andreas Kling 2025-02-26 18:16:36 +01:00 committed by Andreas Kling
commit 8ab61843be
Notes: github-actions[bot] 2025-02-26 23:45:14 +00:00
25 changed files with 185 additions and 67 deletions

View file

@ -38,6 +38,7 @@ Optional<CSSNumericType::BaseType> CSSNumericType::base_type_from_value_type(Val
case ValueType::CustomIdent: case ValueType::CustomIdent:
case ValueType::EasingFunction: case ValueType::EasingFunction:
case ValueType::FilterValueList: case ValueType::FilterValueList:
case ValueType::FitContent:
case ValueType::Image: case ValueType::Image:
case ValueType::Integer: case ValueType::Integer:
case ValueType::Number: case ValueType::Number:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2018-2025, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org> * Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech> * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
@ -30,6 +30,7 @@
#include <LibWeb/CSS/StyleValues/EasingStyleValue.h> #include <LibWeb/CSS/StyleValues/EasingStyleValue.h>
#include <LibWeb/CSS/StyleValues/EdgeStyleValue.h> #include <LibWeb/CSS/StyleValues/EdgeStyleValue.h>
#include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h> #include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h>
#include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/FlexStyleValue.h> #include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h> #include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h> #include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
@ -175,6 +176,12 @@ FilterValueListStyleValue const& CSSStyleValue::as_filter_value_list() const
return static_cast<FilterValueListStyleValue const&>(*this); return static_cast<FilterValueListStyleValue const&>(*this);
} }
FitContentStyleValue const& CSSStyleValue::as_fit_content() const
{
VERIFY(is_fit_content());
return static_cast<FitContentStyleValue const&>(*this);
}
FlexStyleValue const& CSSStyleValue::as_flex() const FlexStyleValue const& CSSStyleValue::as_flex() const
{ {
VERIFY(is_flex()); VERIFY(is_flex());

View file

@ -106,6 +106,7 @@ public:
Easing, Easing,
Edge, Edge,
FilterValueList, FilterValueList,
FitContent,
Flex, Flex,
FontVariant, FontVariant,
Frequency, Frequency,
@ -216,6 +217,10 @@ public:
FilterValueListStyleValue const& as_filter_value_list() const; FilterValueListStyleValue const& as_filter_value_list() const;
FilterValueListStyleValue& as_filter_value_list() { return const_cast<FilterValueListStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_filter_value_list()); } FilterValueListStyleValue& as_filter_value_list() { return const_cast<FilterValueListStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_filter_value_list()); }
[[nodiscard]] bool is_fit_content() const { return type() == Type::FitContent; }
[[nodiscard]] FitContentStyleValue const& as_fit_content() const;
[[nodiscard]] FitContentStyleValue& as_fit_content() { return const_cast<FitContentStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_fit_content()); }
bool is_flex() const { return type() == Type::Flex; } bool is_flex() const { return type() == Type::Flex; }
FlexStyleValue const& as_flex() const; FlexStyleValue const& as_flex() const;
FlexStyleValue& as_flex() { return const_cast<FlexStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_flex()); } FlexStyleValue& as_flex() { return const_cast<FlexStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_flex()); }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2018-2025, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org> * Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -19,6 +19,7 @@
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h> #include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
#include <LibWeb/CSS/StyleValues/CustomIdentStyleValue.h> #include <LibWeb/CSS/StyleValues/CustomIdentStyleValue.h>
#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h> #include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
#include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h> #include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h> #include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h> #include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
@ -158,14 +159,16 @@ Size ComputedProperties::size_value(PropertyID id) const
return Size::make_min_content(); return Size::make_min_content();
case Keyword::MaxContent: case Keyword::MaxContent:
return Size::make_max_content(); return Size::make_max_content();
case Keyword::FitContent:
return Size::make_fit_content();
case Keyword::None: case Keyword::None:
return Size::make_none(); return Size::make_none();
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
if (value.is_fit_content()) {
auto& fit_content = value.as_fit_content();
return Size::make_fit_content(fit_content.length_percentage());
}
if (value.is_calculated()) if (value.is_calculated())
return Size::make_calculated(value.as_calculated()); return Size::make_calculated(value.as_calculated());

View file

@ -175,7 +175,6 @@
"fill", "fill",
"fill-box", "fill-box",
"fine", "fine",
"fit-content",
"fixed", "fixed",
"flex", "flex",
"flex-end", "flex-end",

View file

@ -264,7 +264,7 @@ private:
Optional<Gfx::UnicodeRange> parse_unicode_range(StringView); Optional<Gfx::UnicodeRange> parse_unicode_range(StringView);
Vector<Gfx::UnicodeRange> parse_unicode_ranges(TokenStream<ComponentValue>&); Vector<Gfx::UnicodeRange> parse_unicode_ranges(TokenStream<ComponentValue>&);
Optional<GridSize> parse_grid_size(ComponentValue const&); Optional<GridSize> parse_grid_size(ComponentValue const&);
Optional<GridFitContent> parse_fit_content(Vector<ComponentValue> const&); Optional<GridFitContent> parse_grid_fit_content(Vector<ComponentValue> const&);
Optional<GridMinMax> parse_min_max(Vector<ComponentValue> const&); Optional<GridMinMax> parse_min_max(Vector<ComponentValue> const&);
Optional<GridRepeat> parse_repeat(Vector<ComponentValue> const&); Optional<GridRepeat> parse_repeat(Vector<ComponentValue> const&);
Optional<ExplicitGridTrack> parse_track_sizing_function(ComponentValue const&); Optional<ExplicitGridTrack> parse_track_sizing_function(ComponentValue const&);
@ -275,6 +275,8 @@ private:
Optional<ShapeRadius> parse_shape_radius(TokenStream<ComponentValue>&); Optional<ShapeRadius> parse_shape_radius(TokenStream<ComponentValue>&);
RefPtr<CSSStyleValue> parse_basic_shape_value(TokenStream<ComponentValue>&); RefPtr<CSSStyleValue> parse_basic_shape_value(TokenStream<ComponentValue>&);
RefPtr<FitContentStyleValue> parse_fit_content_value(TokenStream<ComponentValue>&);
template<typename TElement> template<typename TElement>
Optional<Vector<TElement>> parse_color_stop_list(TokenStream<ComponentValue>& tokens, auto parse_position); Optional<Vector<TElement>> parse_color_stop_list(TokenStream<ComponentValue>& tokens, auto parse_position);
Optional<Vector<LinearColorStopListElement>> parse_linear_color_stop_list(TokenStream<ComponentValue>&); Optional<Vector<LinearColorStopListElement>> parse_linear_color_stop_list(TokenStream<ComponentValue>&);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2018-2025, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2020-2021, the SerenityOS developers. * Copyright (c) 2020-2021, the SerenityOS developers.
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org> * Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
@ -31,6 +31,7 @@
#include <LibWeb/CSS/StyleValues/EasingStyleValue.h> #include <LibWeb/CSS/StyleValues/EasingStyleValue.h>
#include <LibWeb/CSS/StyleValues/EdgeStyleValue.h> #include <LibWeb/CSS/StyleValues/EdgeStyleValue.h>
#include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h> #include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h>
#include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/FlexStyleValue.h> #include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h> #include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h> #include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
@ -301,6 +302,12 @@ Optional<Parser::PropertyAndValue> Parser::parse_css_value_for_properties(Readon
} }
} }
if (auto property = any_property_accepts_type(property_ids, ValueType::FitContent); property.has_value()) {
auto context_guard = push_temporary_value_parsing_context(*property);
if (auto value = parse_fit_content_value(tokens))
return PropertyAndValue { *property, value };
}
if (auto property = any_property_accepts_type(property_ids, ValueType::Length); property.has_value()) { if (auto property = any_property_accepts_type(property_ids, ValueType::Length); property.has_value()) {
auto context_guard = push_temporary_value_parsing_context(*property); auto context_guard = push_temporary_value_parsing_context(*property);
if (property_accepts_type(*property, ValueType::Percentage)) { if (property_accepts_type(*property, ValueType::Percentage)) {

View file

@ -35,6 +35,7 @@
#include <LibWeb/CSS/StyleValues/CustomIdentStyleValue.h> #include <LibWeb/CSS/StyleValues/CustomIdentStyleValue.h>
#include <LibWeb/CSS/StyleValues/EasingStyleValue.h> #include <LibWeb/CSS/StyleValues/EasingStyleValue.h>
#include <LibWeb/CSS/StyleValues/EdgeStyleValue.h> #include <LibWeb/CSS/StyleValues/EdgeStyleValue.h>
#include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/FlexStyleValue.h> #include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h> #include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h> #include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
@ -2538,6 +2539,38 @@ Optional<ShapeRadius> Parser::parse_shape_radius(TokenStream<ComponentValue>& to
return {}; return {};
} }
RefPtr<FitContentStyleValue> Parser::parse_fit_content_value(TokenStream<ComponentValue>& tokens)
{
auto transaction = tokens.begin_transaction();
auto& component_value = tokens.consume_a_token();
if (component_value.is_ident("fit-content"sv)) {
transaction.commit();
return FitContentStyleValue::create();
return nullptr;
}
if (!component_value.is_function())
return nullptr;
auto const& function = component_value.function();
if (function.name != "fit-content"sv)
return nullptr;
if (function.value.size() != 1)
return nullptr;
TokenStream argument_tokens { function.value };
argument_tokens.discard_whitespace();
auto maybe_length = parse_length_percentage(argument_tokens);
if (!maybe_length.has_value())
return nullptr;
argument_tokens.discard_whitespace();
if (argument_tokens.has_next_token())
return nullptr;
transaction.commit();
return FitContentStyleValue::create(maybe_length.release_value());
}
RefPtr<CSSStyleValue> Parser::parse_basic_shape_value(TokenStream<ComponentValue>& tokens) RefPtr<CSSStyleValue> Parser::parse_basic_shape_value(TokenStream<ComponentValue>& tokens)
{ {
auto transaction = tokens.begin_transaction(); auto transaction = tokens.begin_transaction();
@ -2875,7 +2908,7 @@ Optional<CSS::GridSize> Parser::parse_grid_size(ComponentValue const& component_
return {}; return {};
} }
Optional<CSS::GridFitContent> Parser::parse_fit_content(Vector<ComponentValue> const& component_values) Optional<CSS::GridFitContent> Parser::parse_grid_fit_content(Vector<ComponentValue> const& component_values)
{ {
// https://www.w3.org/TR/css-grid-2/#valdef-grid-template-columns-fit-content // https://www.w3.org/TR/css-grid-2/#valdef-grid-template-columns-fit-content
// 'fit-content( <length-percentage> )' // 'fit-content( <length-percentage> )'
@ -3050,7 +3083,7 @@ Optional<CSS::ExplicitGridTrack> Parser::parse_track_sizing_function(ComponentVa
else else
return {}; return {};
} else if (function_token.name.equals_ignoring_ascii_case("fit-content"sv)) { } else if (function_token.name.equals_ignoring_ascii_case("fit-content"sv)) {
auto maybe_fit_content_value = parse_fit_content(function_token.value); auto maybe_fit_content_value = parse_grid_fit_content(function_token.value);
if (maybe_fit_content_value.has_value()) if (maybe_fit_content_value.has_value())
return CSS::ExplicitGridTrack(maybe_fit_content_value.value()); return CSS::ExplicitGridTrack(maybe_fit_content_value.value());
return {}; return {};

View file

@ -1131,13 +1131,13 @@
"inherited": false, "inherited": false,
"initial": "auto", "initial": "auto",
"valid-types": [ "valid-types": [
"fit-content",
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]"
], ],
"valid-identifiers": [ "valid-identifiers": [
"auto", "auto",
"content", "content",
"fit-content",
"max-content", "max-content",
"min-content" "min-content"
], ],
@ -1614,12 +1614,12 @@
"inherited": false, "inherited": false,
"initial": "auto", "initial": "auto",
"valid-types": [ "valid-types": [
"fit-content",
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]"
], ],
"valid-identifiers": [ "valid-identifiers": [
"auto", "auto",
"fit-content",
"max-content", "max-content",
"min-content" "min-content"
], ],
@ -2032,11 +2032,11 @@
"inherited": false, "inherited": false,
"initial": "none", "initial": "none",
"valid-types": [ "valid-types": [
"fit-content",
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]"
], ],
"valid-identifiers": [ "valid-identifiers": [
"fit-content",
"max-content", "max-content",
"min-content", "min-content",
"none" "none"
@ -2058,11 +2058,11 @@
"inherited": false, "inherited": false,
"initial": "none", "initial": "none",
"valid-types": [ "valid-types": [
"fit-content",
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]"
], ],
"valid-identifiers": [ "valid-identifiers": [
"fit-content",
"max-content", "max-content",
"min-content", "min-content",
"none" "none"
@ -2084,12 +2084,12 @@
"inherited": false, "inherited": false,
"initial": "auto", "initial": "auto",
"valid-types": [ "valid-types": [
"fit-content",
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]"
], ],
"valid-identifiers": [ "valid-identifiers": [
"auto", "auto",
"fit-content",
"max-content", "max-content",
"min-content" "min-content"
], ],
@ -2110,12 +2110,12 @@
"inherited": false, "inherited": false,
"initial": "auto", "initial": "auto",
"valid-types": [ "valid-types": [
"fit-content",
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]"
], ],
"valid-identifiers": [ "valid-identifiers": [
"auto", "auto",
"fit-content",
"max-content", "max-content",
"min-content" "min-content"
], ],
@ -2936,12 +2936,12 @@
"inherited": false, "inherited": false,
"initial": "auto", "initial": "auto",
"valid-types": [ "valid-types": [
"fit-content",
"length [0,∞]", "length [0,∞]",
"percentage [0,∞]" "percentage [0,∞]"
], ],
"valid-identifiers": [ "valid-identifiers": [
"auto", "auto",
"fit-content",
"max-content", "max-content",
"min-content" "min-content"
], ],

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2021-2025, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2022-2025, Sam Atkins <sam@ladybird.org> * Copyright (c) 2022-2025, Sam Atkins <sam@ladybird.org>
* *
@ -16,6 +16,7 @@
#include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h> #include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
#include <LibWeb/CSS/StyleValues/CSSColorValue.h> #include <LibWeb/CSS/StyleValues/CSSColorValue.h>
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h> #include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
#include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h> #include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h> #include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
#include <LibWeb/CSS/StyleValues/PercentageStyleValue.h> #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
@ -96,9 +97,8 @@ static NonnullRefPtr<CSSStyleValue const> style_value_for_size(Size const& size)
return CSSKeywordValue::create(Keyword::MinContent); return CSSKeywordValue::create(Keyword::MinContent);
if (size.is_max_content()) if (size.is_max_content())
return CSSKeywordValue::create(Keyword::MaxContent); return CSSKeywordValue::create(Keyword::MaxContent);
// FIXME: Support fit-content(<length>)
if (size.is_fit_content()) if (size.is_fit_content())
return CSSKeywordValue::create(Keyword::FitContent); return FitContentStyleValue::create(size.fit_content_available_space());
TODO(); TODO();
} }

View file

@ -54,7 +54,7 @@ Size Size::make_max_content()
return Size { Type::MaxContent, Length::make_auto() }; return Size { Type::MaxContent, Length::make_auto() };
} }
Size Size::make_fit_content(Length available_space) Size Size::make_fit_content(LengthPercentage available_space)
{ {
return Size { Type::FitContent, move(available_space) }; return Size { Type::FitContent, move(available_space) };
} }
@ -78,6 +78,10 @@ bool Size::contains_percentage() const
case Type::MaxContent: case Type::MaxContent:
case Type::None: case Type::None:
return false; return false;
case Type::FitContent:
// FIXME: This should return m_length_percentage.contains_percentage()
// but we have to update a lot of code to handle this.
return false;
default: default:
return m_length_percentage.contains_percentage(); return m_length_percentage.contains_percentage();
} }

View file

@ -32,7 +32,7 @@ public:
static Size make_calculated(NonnullRefPtr<CalculatedStyleValue>); static Size make_calculated(NonnullRefPtr<CalculatedStyleValue>);
static Size make_min_content(); static Size make_min_content();
static Size make_max_content(); static Size make_max_content();
static Size make_fit_content(Length available_space); static Size make_fit_content(LengthPercentage available_space);
static Size make_fit_content(); static Size make_fit_content();
static Size make_none(); static Size make_none();
@ -67,10 +67,10 @@ public:
return m_length_percentage.percentage(); return m_length_percentage.percentage();
} }
CSS::Length const& fit_content_available_space() const CSS::LengthPercentage const& fit_content_available_space() const
{ {
VERIFY(is_fit_content()); VERIFY(is_fit_content());
return m_length_percentage.length(); return m_length_percentage;
} }
String to_string() const; String to_string() const;

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2025, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/PercentageOr.h>
namespace Web::CSS {
class FitContentStyleValue final : public CSSStyleValue {
public:
static ValueComparingNonnullRefPtr<FitContentStyleValue> create()
{
return adopt_ref(*new (nothrow) FitContentStyleValue(LengthPercentage { Length::make_auto() }));
}
static ValueComparingNonnullRefPtr<FitContentStyleValue> create(LengthPercentage length_percentage)
{
return adopt_ref(*new (nothrow) FitContentStyleValue(move(length_percentage)));
}
virtual ~FitContentStyleValue() override = default;
virtual String to_string(SerializationMode) const override
{
if (m_length_percentage.is_auto())
return "fit-content"_string;
return MUST(String::formatted("fit-content({})", m_length_percentage.to_string()));
}
bool equals(CSSStyleValue const& other) const override
{
if (type() != other.type())
return false;
return m_length_percentage == other.as_fit_content().m_length_percentage;
}
[[nodiscard]] LengthPercentage const& length_percentage() const { return m_length_percentage; }
private:
FitContentStyleValue(LengthPercentage length_percentage)
: CSSStyleValue(Type::FitContent)
, m_length_percentage(move(length_percentage))
{
}
LengthPercentage m_length_percentage;
};
}

View file

@ -176,6 +176,7 @@ class EdgeStyleValue;
class ElementInlineCSSStyleDeclaration; class ElementInlineCSSStyleDeclaration;
class ExplicitGridTrack; class ExplicitGridTrack;
class FilterValueListStyleValue; class FilterValueListStyleValue;
class FitContentStyleValue;
class Flex; class Flex;
class FlexOrCalculated; class FlexOrCalculated;
class FlexStyleValue; class FlexStyleValue;

View file

@ -30,6 +30,7 @@ static bool type_name_is_enum(StringView type_name)
"custom-ident"sv, "custom-ident"sv,
"easing-function"sv, "easing-function"sv,
"flex"sv, "flex"sv,
"fit-content"sv,
"frequency"sv, "frequency"sv,
"image"sv, "image"sv,
"integer"sv, "integer"sv,
@ -230,6 +231,7 @@ enum class ValueType {
CustomIdent, CustomIdent,
EasingFunction, EasingFunction,
FilterValueList, FilterValueList,
FitContent,
Flex, Flex,
Frequency, Frequency,
Image, Image,
@ -801,6 +803,8 @@ bool property_accepts_type(PropertyID property_id, ValueType value_type)
property_generator.appendln(" case ValueType::CustomIdent:"); property_generator.appendln(" case ValueType::CustomIdent:");
} else if (type_name == "easing-function") { } else if (type_name == "easing-function") {
property_generator.appendln(" case ValueType::EasingFunction:"); property_generator.appendln(" case ValueType::EasingFunction:");
} else if (type_name == "fit-content") {
property_generator.appendln(" case ValueType::FitContent:");
} else if (type_name == "flex") { } else if (type_name == "flex") {
property_generator.appendln(" case ValueType::Flex:"); property_generator.appendln(" case ValueType::Flex:");
} else if (type_name == "frequency") { } else if (type_name == "frequency") {

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 10 tests Found 10 tests
6 Pass 8 Pass
4 Fail 2 Fail
Pass e.style['height'] = "auto" should set the property value Pass e.style['height'] = "auto" should set the property value
Pass e.style['height'] = "min-content" should set the property value Pass e.style['height'] = "min-content" should set the property value
Pass e.style['height'] = "max-content" should set the property value Pass e.style['height'] = "max-content" should set the property value
@ -11,6 +11,6 @@ Pass e.style['height'] = "0" should set the property value
Pass e.style['height'] = "10%" should set the property value Pass e.style['height'] = "10%" should set the property value
Pass e.style['height'] = "0.5em" should set the property value Pass e.style['height'] = "0.5em" should set the property value
Fail e.style['height'] = "calc(10% - 0.5em)" should set the property value Fail e.style['height'] = "calc(10% - 0.5em)" should set the property value
Fail e.style['height'] = "fit-content(10%)" should set the property value Pass e.style['height'] = "fit-content(10%)" should set the property value
Fail e.style['height'] = "fit-content(0.5em)" should set the property value Pass e.style['height'] = "fit-content(0.5em)" should set the property value
Fail e.style['height'] = "fit-content(calc(10% - 0.5em))" should set the property value Fail e.style['height'] = "fit-content(calc(10% - 0.5em))" should set the property value

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 12 tests Found 12 tests
6 Pass 9 Pass
6 Fail 3 Fail
Pass Property max-height value 'none' Pass Property max-height value 'none'
Pass Property max-height value 'min-content' Pass Property max-height value 'min-content'
Pass Property max-height value 'max-content' Pass Property max-height value 'max-content'
@ -12,7 +12,7 @@ Pass Property max-height value '20%'
Pass Property max-height value 'calc(10% + 40px)' Pass Property max-height value 'calc(10% + 40px)'
Fail Property max-height value 'calc(10px - 0.5em)' Fail Property max-height value 'calc(10px - 0.5em)'
Fail Property max-height value 'calc(10px + 0.5em)' Fail Property max-height value 'calc(10px + 0.5em)'
Fail Property max-height value 'fit-content(10px)' Pass Property max-height value 'fit-content(10px)'
Fail Property max-height value 'fit-content(20%)' Pass Property max-height value 'fit-content(20%)'
Fail Property max-height value 'fit-content(calc(10% + 40px))' Pass Property max-height value 'fit-content(calc(10% + 40px))'
Fail Property max-height value 'fit-content(calc(10px + 0.5em))' Fail Property max-height value 'fit-content(calc(10px + 0.5em))'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 10 tests Found 10 tests
6 Pass 8 Pass
4 Fail 2 Fail
Pass e.style['max-height'] = "none" should set the property value Pass e.style['max-height'] = "none" should set the property value
Pass e.style['max-height'] = "min-content" should set the property value Pass e.style['max-height'] = "min-content" should set the property value
Pass e.style['max-height'] = "max-content" should set the property value Pass e.style['max-height'] = "max-content" should set the property value
@ -11,6 +11,6 @@ Pass e.style['max-height'] = "0" should set the property value
Pass e.style['max-height'] = "10%" should set the property value Pass e.style['max-height'] = "10%" should set the property value
Pass e.style['max-height'] = "0.5em" should set the property value Pass e.style['max-height'] = "0.5em" should set the property value
Fail e.style['max-height'] = "calc(10% - 0.5em)" should set the property value Fail e.style['max-height'] = "calc(10% - 0.5em)" should set the property value
Fail e.style['max-height'] = "fit-content(10%)" should set the property value Pass e.style['max-height'] = "fit-content(10%)" should set the property value
Fail e.style['max-height'] = "fit-content(0.5em)" should set the property value Pass e.style['max-height'] = "fit-content(0.5em)" should set the property value
Fail e.style['max-height'] = "fit-content(calc(10% - 0.5em))" should set the property value Fail e.style['max-height'] = "fit-content(calc(10% - 0.5em))" should set the property value

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 12 tests Found 12 tests
6 Pass 9 Pass
6 Fail 3 Fail
Pass Property max-width value 'none' Pass Property max-width value 'none'
Pass Property max-width value 'min-content' Pass Property max-width value 'min-content'
Pass Property max-width value 'max-content' Pass Property max-width value 'max-content'
@ -12,7 +12,7 @@ Pass Property max-width value '20%'
Pass Property max-width value 'calc(10% + 40px)' Pass Property max-width value 'calc(10% + 40px)'
Fail Property max-width value 'calc(10px - 0.5em)' Fail Property max-width value 'calc(10px - 0.5em)'
Fail Property max-width value 'calc(10px + 0.5em)' Fail Property max-width value 'calc(10px + 0.5em)'
Fail Property max-width value 'fit-content(10px)' Pass Property max-width value 'fit-content(10px)'
Fail Property max-width value 'fit-content(20%)' Pass Property max-width value 'fit-content(20%)'
Fail Property max-width value 'fit-content(calc(10% + 40px))' Pass Property max-width value 'fit-content(calc(10% + 40px))'
Fail Property max-width value 'fit-content(calc(10px + 0.5em))' Fail Property max-width value 'fit-content(calc(10px + 0.5em))'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 10 tests Found 10 tests
6 Pass 8 Pass
4 Fail 2 Fail
Pass e.style['max-width'] = "none" should set the property value Pass e.style['max-width'] = "none" should set the property value
Pass e.style['max-width'] = "min-content" should set the property value Pass e.style['max-width'] = "min-content" should set the property value
Pass e.style['max-width'] = "max-content" should set the property value Pass e.style['max-width'] = "max-content" should set the property value
@ -11,6 +11,6 @@ Pass e.style['max-width'] = "0" should set the property value
Pass e.style['max-width'] = "10%" should set the property value Pass e.style['max-width'] = "10%" should set the property value
Pass e.style['max-width'] = "0.5em" should set the property value Pass e.style['max-width'] = "0.5em" should set the property value
Fail e.style['max-width'] = "calc(10% - 0.5em)" should set the property value Fail e.style['max-width'] = "calc(10% - 0.5em)" should set the property value
Fail e.style['max-width'] = "fit-content(10%)" should set the property value Pass e.style['max-width'] = "fit-content(10%)" should set the property value
Fail e.style['max-width'] = "fit-content(0.5em)" should set the property value Pass e.style['max-width'] = "fit-content(0.5em)" should set the property value
Fail e.style['max-width'] = "fit-content(calc(10% - 0.5em))" should set the property value Fail e.style['max-width'] = "fit-content(calc(10% - 0.5em))" should set the property value

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 11 tests Found 11 tests
5 Pass 8 Pass
6 Fail 3 Fail
Pass Property min-height value 'min-content' Pass Property min-height value 'min-content'
Pass Property min-height value 'max-content' Pass Property min-height value 'max-content'
Pass Property min-height value '10px' Pass Property min-height value '10px'
@ -11,7 +11,7 @@ Pass Property min-height value '20%'
Pass Property min-height value 'calc(10% + 40px)' Pass Property min-height value 'calc(10% + 40px)'
Fail Property min-height value 'calc(10px - 0.5em)' Fail Property min-height value 'calc(10px - 0.5em)'
Fail Property min-height value 'calc(10px + 0.5em)' Fail Property min-height value 'calc(10px + 0.5em)'
Fail Property min-height value 'fit-content(10px)' Pass Property min-height value 'fit-content(10px)'
Fail Property min-height value 'fit-content(20%)' Pass Property min-height value 'fit-content(20%)'
Fail Property min-height value 'fit-content(calc(10% + 40px))' Pass Property min-height value 'fit-content(calc(10% + 40px))'
Fail Property min-height value 'fit-content(calc(10px + 0.5em))' Fail Property min-height value 'fit-content(calc(10px + 0.5em))'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 10 tests Found 10 tests
6 Pass 8 Pass
4 Fail 2 Fail
Pass e.style['min-height'] = "auto" should set the property value Pass e.style['min-height'] = "auto" should set the property value
Pass e.style['min-height'] = "min-content" should set the property value Pass e.style['min-height'] = "min-content" should set the property value
Pass e.style['min-height'] = "max-content" should set the property value Pass e.style['min-height'] = "max-content" should set the property value
@ -11,6 +11,6 @@ Pass e.style['min-height'] = "0" should set the property value
Pass e.style['min-height'] = "10%" should set the property value Pass e.style['min-height'] = "10%" should set the property value
Pass e.style['min-height'] = "0.5em" should set the property value Pass e.style['min-height'] = "0.5em" should set the property value
Fail e.style['min-height'] = "calc(10% - 0.5em)" should set the property value Fail e.style['min-height'] = "calc(10% - 0.5em)" should set the property value
Fail e.style['min-height'] = "fit-content(10%)" should set the property value Pass e.style['min-height'] = "fit-content(10%)" should set the property value
Fail e.style['min-height'] = "fit-content(0.5em)" should set the property value Pass e.style['min-height'] = "fit-content(0.5em)" should set the property value
Fail e.style['min-height'] = "fit-content(calc(10% - 0.5em))" should set the property value Fail e.style['min-height'] = "fit-content(calc(10% - 0.5em))" should set the property value

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 11 tests Found 11 tests
5 Pass 8 Pass
6 Fail 3 Fail
Pass Property min-width value 'min-content' Pass Property min-width value 'min-content'
Pass Property min-width value 'max-content' Pass Property min-width value 'max-content'
Pass Property min-width value '10px' Pass Property min-width value '10px'
@ -11,7 +11,7 @@ Pass Property min-width value '20%'
Pass Property min-width value 'calc(10% + 40px)' Pass Property min-width value 'calc(10% + 40px)'
Fail Property min-width value 'calc(10px - 0.5em)' Fail Property min-width value 'calc(10px - 0.5em)'
Fail Property min-width value 'calc(10px + 0.5em)' Fail Property min-width value 'calc(10px + 0.5em)'
Fail Property min-width value 'fit-content(10px)' Pass Property min-width value 'fit-content(10px)'
Fail Property min-width value 'fit-content(20%)' Pass Property min-width value 'fit-content(20%)'
Fail Property min-width value 'fit-content(calc(10% + 40px))' Pass Property min-width value 'fit-content(calc(10% + 40px))'
Fail Property min-width value 'fit-content(calc(10px + 0.5em))' Fail Property min-width value 'fit-content(calc(10px + 0.5em))'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 10 tests Found 10 tests
6 Pass 8 Pass
4 Fail 2 Fail
Pass e.style['min-width'] = "auto" should set the property value Pass e.style['min-width'] = "auto" should set the property value
Pass e.style['min-width'] = "min-content" should set the property value Pass e.style['min-width'] = "min-content" should set the property value
Pass e.style['min-width'] = "max-content" should set the property value Pass e.style['min-width'] = "max-content" should set the property value
@ -11,6 +11,6 @@ Pass e.style['min-width'] = "0" should set the property value
Pass e.style['min-width'] = "10%" should set the property value Pass e.style['min-width'] = "10%" should set the property value
Pass e.style['min-width'] = "0.5em" should set the property value Pass e.style['min-width'] = "0.5em" should set the property value
Fail e.style['min-width'] = "calc(10% - 0.5em)" should set the property value Fail e.style['min-width'] = "calc(10% - 0.5em)" should set the property value
Fail e.style['min-width'] = "fit-content(10%)" should set the property value Pass e.style['min-width'] = "fit-content(10%)" should set the property value
Fail e.style['min-width'] = "fit-content(0.5em)" should set the property value Pass e.style['min-width'] = "fit-content(0.5em)" should set the property value
Fail e.style['min-width'] = "fit-content(calc(10% - 0.5em))" should set the property value Fail e.style['min-width'] = "fit-content(calc(10% - 0.5em))" should set the property value

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 10 tests Found 10 tests
6 Pass 8 Pass
4 Fail 2 Fail
Pass e.style['width'] = "auto" should set the property value Pass e.style['width'] = "auto" should set the property value
Pass e.style['width'] = "min-content" should set the property value Pass e.style['width'] = "min-content" should set the property value
Pass e.style['width'] = "max-content" should set the property value Pass e.style['width'] = "max-content" should set the property value
@ -11,6 +11,6 @@ Pass e.style['width'] = "0" should set the property value
Pass e.style['width'] = "10%" should set the property value Pass e.style['width'] = "10%" should set the property value
Pass e.style['width'] = "0.5em" should set the property value Pass e.style['width'] = "0.5em" should set the property value
Fail e.style['width'] = "calc(10% - 0.5em)" should set the property value Fail e.style['width'] = "calc(10% - 0.5em)" should set the property value
Fail e.style['width'] = "fit-content(10%)" should set the property value Pass e.style['width'] = "fit-content(10%)" should set the property value
Fail e.style['width'] = "fit-content(0.5em)" should set the property value Pass e.style['width'] = "fit-content(0.5em)" should set the property value
Fail e.style['width'] = "fit-content(calc(10% - 0.5em))" should set the property value Fail e.style['width'] = "fit-content(calc(10% - 0.5em))" should set the property value