ladybird/Libraries/LibWeb/CSS/Parser/ArbitrarySubstitutionFunctions.h
Sam Atkins 89b59cb5c3 LibWeb/CSS: Implement env() as an arbitrary substitution function
Technically, env() should not be an ASF. (😱) This is why some tests
still fail - env() as specced is expected to have its syntax checked
fully at parse-time, whereas ASFs are not properly syntax-checked until
later. However, I think this approach was worth doing for a few reasons:

- env() behaves like an ASF otherwise. (It is replaced with a set of
  arbitrary component-values that are not known until computed-value
  time.)
- env() was defined before the ASF concept existed, so I strongly
  suspect it will be updated in the future to match that definition,
  with a couple of adjustments. (eg, env() is allowed in some extra
  places compared to var() and attr().)
- This was much quicker and easier to implement (under 3 hours in total)
  compared to the greater amount of work to implement a whole separate
  system just for env().
- Most of these tests are marked tentative, and the spec definition of
  env() is still somewhat in flux, so failing some is not a huge deal.

If in the future I turn out to be wrong on this, we can convert it to
its own special thing.
2025-08-07 16:38:29 +02:00

55 lines
1.7 KiB
C++

/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/Parser/Parser.h>
namespace Web::CSS::Parser {
// https://drafts.csswg.org/css-values-5/#substitution-context
struct SubstitutionContext {
enum class DependencyType : u8 {
Property,
Attribute,
Function,
};
DependencyType dependency_type;
String first;
Optional<String> second {};
bool is_cyclic { false };
bool operator==(SubstitutionContext const&) const;
String to_string() const;
};
class GuardedSubstitutionContexts {
public:
void guard(SubstitutionContext&);
void unguard(SubstitutionContext const&);
private:
Vector<SubstitutionContext&> m_contexts;
};
enum class ArbitrarySubstitutionFunction : u8 {
Attr,
Env,
Var,
};
[[nodiscard]] Optional<ArbitrarySubstitutionFunction> to_arbitrary_substitution_function(FlyString const& name);
bool contains_guaranteed_invalid_value(Vector<ComponentValue> const&);
[[nodiscard]] Vector<ComponentValue> substitute_arbitrary_substitution_functions(DOM::AbstractElement&, GuardedSubstitutionContexts&, Vector<ComponentValue> const&, Optional<SubstitutionContext> = {});
using ArbitrarySubstitutionFunctionArguments = Vector<Vector<ComponentValue>>;
[[nodiscard]] Optional<ArbitrarySubstitutionFunctionArguments> parse_according_to_argument_grammar(ArbitrarySubstitutionFunction, Vector<ComponentValue> const&);
[[nodiscard]] Vector<ComponentValue> replace_an_arbitrary_substitution_function(DOM::AbstractElement&, GuardedSubstitutionContexts&, ArbitrarySubstitutionFunction, ArbitrarySubstitutionFunctionArguments const&);
}