ladybird/Libraries/LibWeb/CSS/StyleValues/CounterStyleSystemStyleValue.cpp

143 lines
6.1 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2026, Callum Law <callumlaw1709@outlook.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CounterStyleSystemStyleValue.h"
#include <LibWeb/CSS/Enums.h>
#include <LibWeb/CSS/Serialize.h>
namespace Web::CSS {
void CounterStyleSystemStyleValue::serialize(StringBuilder& builder, SerializationMode mode) const
{
m_value.visit(
[&](CounterStyleSystem const& system) {
builder.append(CSS::to_string(system));
},
[&](Fixed const& fixed) {
builder.append("fixed"sv);
if (fixed.first_symbol) {
builder.append(' ');
fixed.first_symbol->serialize(builder, mode);
}
},
[&](Extends const& extends) {
builder.append("extends "sv);
serialize_an_identifier(builder, extends.name);
});
}
ValueComparingNonnullRefPtr<StyleValue const> CounterStyleSystemStyleValue::absolutized(ComputationContext const& context) const
{
return m_value.visit(
[&](CounterStyleSystem const&) -> ValueComparingNonnullRefPtr<StyleValue const> {
return *this;
},
[&](Fixed const& fixed) -> ValueComparingNonnullRefPtr<StyleValue const> {
if (!fixed.first_symbol)
return *this;
auto const& absolutized_value = fixed.first_symbol->absolutized(context);
if (absolutized_value == fixed.first_symbol)
return *this;
return CounterStyleSystemStyleValue::create_fixed(absolutized_value);
},
[&](Extends const&) -> ValueComparingNonnullRefPtr<StyleValue const> {
return *this;
});
}
bool CounterStyleSystemStyleValue::algorithm_differs_from(CounterStyleSystemStyleValue const& other) const
{
if (m_value.index() != other.m_value.index())
return true;
return m_value.visit(
[&](CounterStyleSystem const& system) -> bool {
return system != other.m_value.get<CounterStyleSystem>();
},
[&](Fixed const&) -> bool {
return false;
},
[&](Extends const& extends) -> bool {
// FIXME: We don't know which counter style the 'extends' refers to here, so we have to assume it might
// differ if the names differ. Is this correct?
return extends.name != other.m_value.get<Extends>().name;
});
}
bool CounterStyleSystemStyleValue::is_valid_symbol_count(size_t count) const
{
return m_value.visit(
[&](CounterStyleSystem const& system) -> bool {
switch (system) {
// https://drafts.csswg.org/css-counter-styles-3/#cyclic-system
// If the system is cyclic, the symbols descriptor must contain at least one counter symbol, otherwise the
// rule does not define a counter style (but is still a valid rule)
case CounterStyleSystem::Cyclic:
// https://drafts.csswg.org/css-counter-styles-3/#symbolic-system
// If the system is symbolic, the symbols descriptor must contain at least one counter symbol, otherwise the
// rule does not define a counter style (but is still a valid rule).
case CounterStyleSystem::Symbolic:
return count >= 1;
// https://drafts.csswg.org/css-counter-styles-3/#alphabetic-system
// If the system is alphabetic, the symbols descriptor must contain at least two counter symbols, otherwise
// the rule does not define a counter style (but is still a valid rule).
case CounterStyleSystem::Alphabetic:
// https://drafts.csswg.org/css-counter-styles-3/#numeric-system
// If the system is numeric, the symbols descriptor must contain at least two counter symbols, otherwise the
// rule does not define a counter style (but is still a valid rule).
case CounterStyleSystem::Numeric:
return count >= 2;
case CounterStyleSystem::Additive:
// NB: Additive relies on the `additive-symbols` descriptor instead and `symbols` is ignored.
return true;
}
VERIFY_NOT_REACHED();
},
[&](Fixed const&) -> bool {
// https://drafts.csswg.org/css-counter-styles-3/#fixed-system
// If the system is fixed, the symbols descriptor must contain at least one counter symbol, otherwise the
// rule does not define a counter style (but is still a valid rule).
return count >= 1;
},
[&](Extends const&) -> bool {
// https://drafts.csswg.org/css-counter-styles-3/#extends-system
// If a @counter-style uses the extends system, it must not contain a symbols or additive-symbols
// descriptor, otherwise the rule does not define a counter style (but is still a valid rule).
return false;
});
}
bool CounterStyleSystemStyleValue::is_valid_additive_symbol_count(size_t count) const
{
return m_value.visit(
[&](CounterStyleSystem const& system) -> bool {
// https://drafts.csswg.org/css-counter-styles-3/#additive-system
// If the system is additive, the additive-symbols descriptor must contain at least one additive tuple,
// otherwise the rule does not define a counter style (but is still a valid rule).
if (system == CounterStyleSystem::Additive)
return count >= 1;
// NB: Other systems ignore rely on the `symbols` descriptor instead and `additive-symbols` is ignored.
return true;
},
[&](Fixed const&) -> bool {
// NB: Fixed relies on the `symbols` descriptor instead and `additive-symbols` is ignored.
return true;
},
[&](Extends const&) -> bool {
// https://drafts.csswg.org/css-counter-styles-3/#extends-system
// If a @counter-style uses the extends system, it must not contain a symbols or additive-symbols
// descriptor, otherwise the rule does not define a counter style (but is still a valid rule).
return false;
});
}
}