chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PARSING_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PARSING_UTILS_H_

#include <optional>

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_anchor_query_enums.h"
#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_repeat_style_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
#include "third_party/blink/renderer/core/style/grid_area.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
#include "third_party/blink/renderer/platform/heap/member.h"

namespace blink {

namespace cssvalue {
class CSSFontFeatureValue;
class CSSURIValue;
}  // namespace cssvalue
class CSSIdentifierValue;
class CSSParserContext;
class CSSParserLocalContext;
class CSSParserTokenStream;
class CSSPropertyValue;
class CSSShadowValue;
class CSSStringValue;
class CSSValue;
class CSSValueList;
class CSSValuePair;
class StylePropertyShorthand;

// "Consume" functions, when successful, should consume all the relevant tokens
// as well as any trailing whitespace. When the start of the range doesn't
// match the type we're looking for, the range should not be modified.
namespace css_parsing_utils {

enum class AllowInsetAndSpread {};
enum class AllowTextValue {};
enum class AllowPathValue {};
enum class AllowBasicShapeRectValue {};
enum class AllowBasicShapeXYWHValue {};
enum class DefaultFill {};
enum class ParsingStyle {};
enum class TrackListType {};
enum class UnitlessQuirk {};
enum class AllowCalcSize {};
enum class AllowedColors {};
enum class EmptyPathStringHandling {};

ConsumeAnimationItemValue;
IsResetOnlyFunction;
IsPositionKeyword;

constexpr size_t kMaxNumAnimationLonghands =;

void Complete4Sides(CSSValue* side[4]);

// TODO(timloh): These should probably just be consumeComma and consumeSlash.
bool ConsumeCommaIncludingWhitespace(CSSParserTokenRange&);
bool ConsumeCommaIncludingWhitespace(CSSParserTokenStream&);
bool ConsumeSlashIncludingWhitespace(CSSParserTokenRange&);
bool ConsumeSlashIncludingWhitespace(CSSParserTokenStream&);
// ConsumeFunction expects the range starts with a FunctionToken.
CSSParserTokenRange ConsumeFunction(CSSParserTokenRange&);
CSSParserTokenRange ConsumeFunction(CSSParserTokenStream&);

// https://drafts.csswg.org/css-syntax/#typedef-any-value
//
// Consumes component values until it reaches a token that is not allowed
// for <any-value>.
CORE_EXPORT bool ConsumeAnyValue(CSSParserTokenRange&);
CORE_EXPORT void ConsumeAnyValue(CSSParserTokenStream&);

CSSPrimitiveValue* ConsumeInteger(
    CSSParserTokenRange&,
    const CSSParserContext&,
    double minimum_value = -std::numeric_limits<double>::max(),
    const bool is_percentage_allowed = true);
CSSPrimitiveValue* ConsumeInteger(
    CSSParserTokenStream&,
    const CSSParserContext&,
    double minimum_value = -std::numeric_limits<double>::max(),
    const bool is_percentage_allowed = true);
CSSPrimitiveValue* ConsumeIntegerOrNumberCalc(
    CSSParserTokenStream&,
    const CSSParserContext&,
    CSSPrimitiveValue::ValueRange = CSSPrimitiveValue::ValueRange::kInteger);
CSSPrimitiveValue* ConsumePositiveInteger(CSSParserTokenStream&,
                                          const CSSParserContext&);
bool ConsumeNumberRaw(CSSParserTokenStream&,
                      const CSSParserContext& context,
                      double& result);
CSSPrimitiveValue* ConsumeNumber(CSSParserTokenRange&,
                                 const CSSParserContext&,
                                 CSSPrimitiveValue::ValueRange);
CSSPrimitiveValue* ConsumeNumber(CSSParserTokenStream&,
                                 const CSSParserContext&,
                                 CSSPrimitiveValue::ValueRange);
CSSPrimitiveValue* ConsumeLength(CSSParserTokenRange&,
                                 const CSSParserContext&,
                                 CSSPrimitiveValue::ValueRange,
                                 UnitlessQuirk = UnitlessQuirk::kForbid);
CSSPrimitiveValue* ConsumeLength(CSSParserTokenStream&,
                                 const CSSParserContext&,
                                 CSSPrimitiveValue::ValueRange,
                                 UnitlessQuirk = UnitlessQuirk::kForbid);
CSSPrimitiveValue* ConsumePercent(CSSParserTokenRange&,
                                  const CSSParserContext&,
                                  CSSPrimitiveValue::ValueRange);
CSSPrimitiveValue* ConsumePercent(CSSParserTokenStream&,
                                  const CSSParserContext&,
                                  CSSPrimitiveValue::ValueRange);

// Any percentages are converted to numbers.
CSSPrimitiveValue* ConsumeNumberOrPercent(
    CSSParserTokenStream& stream,
    const CSSParserContext& context,
    CSSPrimitiveValue::ValueRange value_range);

CSSPrimitiveValue* ConsumeAlphaValue(CSSParserTokenStream&,
                                     const CSSParserContext&);
CSSPrimitiveValue* ConsumeLengthOrPercent(
    CSSParserTokenRange&,
    const CSSParserContext&,
    CSSPrimitiveValue::ValueRange,
    UnitlessQuirk = UnitlessQuirk::kForbid,
    CSSAnchorQueryTypes = kCSSAnchorQueryTypesNone,
    AllowCalcSize = AllowCalcSize::kForbid);
CSSPrimitiveValue* ConsumeLengthOrPercent(
    CSSParserTokenStream&,
    const CSSParserContext&,
    CSSPrimitiveValue::ValueRange,
    UnitlessQuirk = UnitlessQuirk::kForbid,
    CSSAnchorQueryTypes = kCSSAnchorQueryTypesNone,
    AllowCalcSize = AllowCalcSize::kForbid);
CSSPrimitiveValue* ConsumeSVGGeometryPropertyLength(
    CSSParserTokenStream&,
    const CSSParserContext&,
    CSSPrimitiveValue::ValueRange);

CORE_EXPORT CSSPrimitiveValue* ConsumeAngle(
    CSSParserTokenRange&,
    const CSSParserContext&,
    std::optional<WebFeature> unitless_zero_feature);
CORE_EXPORT CSSPrimitiveValue* ConsumeAngle(
    CSSParserTokenRange&,
    const CSSParserContext&,
    std::optional<WebFeature> unitless_zero_feature,
    double minimum_value,
    double maximum_value);
CORE_EXPORT CSSPrimitiveValue* ConsumeAngle(
    CSSParserTokenStream&,
    const CSSParserContext&,
    std::optional<WebFeature> unitless_zero_feature);
CORE_EXPORT CSSPrimitiveValue* ConsumeAngle(
    CSSParserTokenStream&,
    const CSSParserContext&,
    std::optional<WebFeature> unitless_zero_feature,
    double minimum_value,
    double maximum_value);
CSSPrimitiveValue* ConsumeTime(CSSParserTokenStream&,
                               const CSSParserContext&,
                               CSSPrimitiveValue::ValueRange);
template <typename T>
  requires std::is_same_v<T, CSSParserTokenStream> ||
           std::is_same_v<T, CSSParserTokenRange>
CSSPrimitiveValue* ConsumeResolution(T&, const CSSParserContext&);
CSSValue* ConsumeRatio(CSSParserTokenStream&, const CSSParserContext&);
CSSIdentifierValue* ConsumeIdent(CSSParserTokenRange&);
CSSIdentifierValue* ConsumeIdent(CSSParserTokenStream&);
CSSIdentifierValue* ConsumeIdentRange(CSSParserTokenRange&,
                                      CSSValueID lower,
                                      CSSValueID upper);
CSSIdentifierValue* ConsumeIdentRange(CSSParserTokenStream&,
                                      CSSValueID lower,
                                      CSSValueID upper);
template <CSSValueID, CSSValueID...>
inline bool IdentMatches(CSSValueID id);
template <CSSValueID... allowedIdents>
CSSIdentifierValue* ConsumeIdent(CSSParserTokenRange&);
template <CSSValueID... allowedIdents>
CSSIdentifierValue* ConsumeIdent(CSSParserTokenStream&);

CSSCustomIdentValue* ConsumeCustomIdent(CSSParserTokenRange&,
                                        const CSSParserContext&);
CSSCustomIdentValue* ConsumeCustomIdent(CSSParserTokenStream&,
                                        const CSSParserContext&);
template <typename T>
  requires std::is_same_v<T, CSSParserTokenStream> ||
           std::is_same_v<T, CSSParserTokenRange>
CSSCustomIdentValue* ConsumeDashedIdent(T&, const CSSParserContext&);
CSSStringValue* ConsumeString(CSSParserTokenStream&);
cssvalue::CSSURIValue* ConsumeUrl(CSSParserTokenStream&,
                                  const CSSParserContext&);

// Some properties accept non-standard colors, like rgb values without a
// preceding hash, in quirks mode.
CORE_EXPORT CSSValue* ConsumeColorMaybeQuirky(CSSParserTokenStream&,
                                              const CSSParserContext&);

// https://drafts.csswg.org/css-color-5/#typedef-color
CORE_EXPORT CSSValue* ConsumeColor(CSSParserTokenStream&,
                                   const CSSParserContext&);

// https://drafts.csswg.org/css-color-5/#absolute-color
CORE_EXPORT CSSValue* ConsumeAbsoluteColor(CSSParserTokenStream&,
                                           const CSSParserContext&);

CSSValue* ConsumeLineWidth(CSSParserTokenStream&,
                           const CSSParserContext&,
                           UnitlessQuirk);

CSSValuePair* ConsumePosition(CSSParserTokenStream&,
                              const CSSParserContext&,
                              UnitlessQuirk,
                              std::optional<WebFeature> three_value_position);
bool ConsumePosition(CSSParserTokenStream&,
                     const CSSParserContext&,
                     UnitlessQuirk,
                     std::optional<WebFeature> three_value_position,
                     CSSValue*& result_x,
                     CSSValue*& result_y);
bool ConsumeOneOrTwoValuedPosition(CSSParserTokenStream&,
                                   const CSSParserContext&,
                                   UnitlessQuirk,
                                   CSSValue*& result_x,
                                   CSSValue*& result_y);
bool ConsumeBorderShorthand(CSSParserTokenStream&,
                            const CSSParserContext&,
                            const CSSParserLocalContext&,
                            const CSSValue*& result_width,
                            const CSSValue*& result_style,
                            const CSSValue*& result_color);

enum class ConsumeGeneratedImagePolicy {};
enum class ConsumeStringUrlImagePolicy {};
enum class ConsumeImageSetImagePolicy {};

CSSValue* ConsumeImage(
    CSSParserTokenStream&,
    const CSSParserContext&,
    const ConsumeGeneratedImagePolicy = ConsumeGeneratedImagePolicy::kAllow,
    const ConsumeStringUrlImagePolicy = ConsumeStringUrlImagePolicy::kForbid,
    const ConsumeImageSetImagePolicy = ConsumeImageSetImagePolicy::kAllow);
CSSValue* ConsumeImageOrNone(CSSParserTokenStream&, const CSSParserContext&);

CSSValue* ConsumeAxis(CSSParserTokenStream&, const CSSParserContext& context);

// Syntax: none | <length> | auto && <length> | auto && none
// If this returns a CSSIdentifierValue then it is "none"
// Otherwise, this returns a list of 1 or 2 elements for the rest of the syntax
CSSValue* ConsumeIntrinsicSizeLonghand(CSSParserTokenStream&,
                                       const CSSParserContext&);

CSSIdentifierValue* ConsumeShapeBox(CSSParserTokenStream&);
CSSIdentifierValue* ConsumeVisualBox(CSSParserTokenStream&);

CSSIdentifierValue* ConsumeCoordBox(CSSParserTokenStream&);

CSSIdentifierValue* ConsumeGeometryBox(CSSParserTokenStream&);

enum class IsImplicitProperty {};

void AddProperty(CSSPropertyID resolved_property,
                 CSSPropertyID current_shorthand,
                 const CSSValue&,
                 bool important,
                 IsImplicitProperty,
                 HeapVector<CSSPropertyValue, 64>& properties);

void CountKeywordOnlyPropertyUsage(CSSPropertyID,
                                   const CSSParserContext&,
                                   CSSValueID);

void WarnInvalidKeywordPropertyUsage(CSSPropertyID,
                                     const CSSParserContext&,
                                     CSSValueID);

const CSSValue* ParseLonghand(CSSPropertyID unresolved_property,
                              CSSPropertyID current_shorthand,
                              const CSSParserContext&,
                              CSSParserTokenStream&);

bool ConsumeShorthandVia2Longhands(
    const StylePropertyShorthand&,
    bool important,
    const CSSParserContext&,
    CSSParserTokenStream&,
    HeapVector<CSSPropertyValue, 64>& properties);

bool ConsumeShorthandVia4Longhands(
    const StylePropertyShorthand&,
    bool important,
    const CSSParserContext&,
    CSSParserTokenStream&,
    HeapVector<CSSPropertyValue, 64>& properties);

bool ConsumeShorthandGreedilyViaLonghands(
    const StylePropertyShorthand&,
    bool important,
    const CSSParserContext&,
    CSSParserTokenStream&,
    HeapVector<CSSPropertyValue, 64>& properties,
    bool use_initial_value_function = false);

void AddExpandedPropertyForValue(CSSPropertyID prop_id,
                                 const CSSValue&,
                                 bool,
                                 HeapVector<CSSPropertyValue, 64>& properties);

CSSValue* ConsumeTransformValue(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeTransformList(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeFilterFunctionList(CSSParserTokenStream&,
                                    const CSSParserContext&);

bool IsBaselineKeyword(CSSValueID id);
bool IsSelfPositionKeyword(CSSValueID);
bool IsSelfPositionOrLeftOrRightKeyword(CSSValueID);
bool IsContentPositionKeyword(CSSValueID);
bool IsContentPositionOrLeftOrRightKeyword(CSSValueID);
CORE_EXPORT bool IsCSSWideKeyword(CSSValueID);
CORE_EXPORT bool IsCSSWideKeyword(StringView);
bool IsRevertKeyword(StringView);
bool IsDefaultKeyword(StringView);
bool IsHashIdentifier(const CSSParserToken&);
CORE_EXPORT bool IsDashedIdent(const CSSParserToken&);

CSSValue* ConsumeCSSWideKeyword(CSSParserTokenStream&);

// This function returns false for CSS-wide keywords, 'default', and any
// template parameters provided.
//
// https://drafts.csswg.org/css-values-4/#identifier-value
template <CSSValueID, CSSValueID...>
bool IsCustomIdent(CSSValueID);

// https://drafts.csswg.org/scroll-animations-1/#typedef-timeline-name
bool IsTimelineName(const CSSParserToken&);

CSSValue* ConsumeSelfPositionOverflowPosition(CSSParserTokenStream&,
                                              IsPositionKeyword);
CSSValue* ConsumeContentDistributionOverflowPosition(CSSParserTokenStream&,
                                                     IsPositionKeyword);

CSSValue* ConsumeAnimationIterationCount(CSSParserTokenStream&,
                                         const CSSParserContext&);
CSSValue* ConsumeAnimationName(CSSParserTokenStream&,
                               const CSSParserContext&,
                               bool allow_quoted_name);
CSSValue* ConsumeAnimationTimeline(CSSParserTokenStream&,
                                   const CSSParserContext&);
CSSValue* ConsumeAnimationTimingFunction(CSSParserTokenStream&,
                                         const CSSParserContext&);
CSSValue* ConsumeAnimationDuration(CSSParserTokenStream&,
                                   const CSSParserContext&);
// https://drafts.csswg.org/scroll-animations-1/#typedef-timeline-range-name
CSSValue* ConsumeTimelineRangeName(CSSParserTokenStream&);
CSSValue* ConsumeTimelineRangeName(CSSParserTokenRange&);
template <typename T>
  requires std::is_same_v<T, CSSParserTokenStream> ||
           std::is_same_v<T, CSSParserTokenRange>
CSSValue* ConsumeTimelineRangeNameAndPercent(T&, const CSSParserContext&);
CSSValue* ConsumeAnimationDelay(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeAnimationRange(CSSParserTokenStream&,
                                const CSSParserContext&,
                                double default_offset_percent);

bool ConsumeAnimationShorthand(
    const StylePropertyShorthand&,
    HeapVector<Member<CSSValueList>, kMaxNumAnimationLonghands>&,
    ConsumeAnimationItemValue,
    IsResetOnlyFunction,
    CSSParserTokenStream&,
    const CSSParserContext&,
    bool use_legacy_parsing);

CSSValue* ConsumeSingleTimelineAxis(CSSParserTokenStream&);
CSSValue* ConsumeSingleTimelineName(CSSParserTokenStream&,
                                    const CSSParserContext&);
CSSValue* ConsumeSingleTimelineInset(CSSParserTokenStream&,
                                     const CSSParserContext&);

void AddBackgroundValue(CSSValue*& list, const CSSValue*);
CSSValue* ConsumeBackgroundAttachment(CSSParserTokenStream&);
CSSValue* ConsumeBackgroundBlendMode(CSSParserTokenStream&);
CSSValue* ConsumeBackgroundBox(CSSParserTokenStream&);
CSSValue* ConsumeBackgroundBoxOrText(CSSParserTokenStream&);
CSSValue* ConsumeMaskComposite(CSSParserTokenStream&);
CSSValue* ConsumePrefixedMaskComposite(CSSParserTokenStream&);
CSSValue* ConsumeMaskMode(CSSParserTokenStream&);
bool ConsumeBackgroundPosition(CSSParserTokenStream&,
                               const CSSParserContext&,
                               UnitlessQuirk,
                               std::optional<WebFeature> three_value_position,
                               const CSSValue*& result_x,
                               const CSSValue*& result_y);
CSSValue* ConsumePrefixedBackgroundBox(CSSParserTokenStream&, AllowTextValue);
CSSValue* ParseBackgroundBox(CSSParserTokenStream&,
                             const CSSParserLocalContext&,
                             AllowTextValue alias_allow_text_value);
CSSValue* ParseBackgroundSize(CSSParserTokenStream&,
                              const CSSParserContext&,
                              const CSSParserLocalContext&,
                              std::optional<WebFeature> negative_size);
CSSValue* ParseMaskSize(CSSParserTokenStream&,
                        const CSSParserContext&,
                        const CSSParserLocalContext&,
                        std::optional<WebFeature> negative_size);
bool ParseBackgroundOrMask(bool,
                           CSSParserTokenStream&,
                           const CSSParserContext&,
                           const CSSParserLocalContext&,
                           HeapVector<CSSPropertyValue, 64>&);

CSSValue* ConsumeCoordBoxOrNoClip(CSSParserTokenStream&);

CSSRepeatStyleValue* ConsumeRepeatStyleValue(CSSParserTokenStream& range);
CSSValueList* ParseRepeatStyle(CSSParserTokenStream& stream);

CSSValue* ConsumeWebkitBorderImage(CSSParserTokenStream&,
                                   const CSSParserContext&);
bool ConsumeBorderImageComponents(CSSParserTokenStream&,
                                  const CSSParserContext&,
                                  CSSValue*& source,
                                  CSSValue*& slice,
                                  CSSValue*& width,
                                  CSSValue*& outset,
                                  CSSValue*& repeat,
                                  DefaultFill);
CSSValue* ConsumeBorderImageRepeat(CSSParserTokenStream&);
CSSValue* ConsumeBorderImageSlice(CSSParserTokenStream&,
                                  const CSSParserContext&,
                                  DefaultFill);
CSSValue* ConsumeBorderImageWidth(CSSParserTokenStream&,
                                  const CSSParserContext&);
CSSValue* ConsumeBorderImageOutset(CSSParserTokenStream&,
                                   const CSSParserContext&);

CSSValue* ParseBorderRadiusCorner(CSSParserTokenStream&,
                                  const CSSParserContext&);
CSSValue* ParseBorderWidthSide(CSSParserTokenStream&,
                               const CSSParserContext&,
                               const CSSParserLocalContext&);
const CSSValue* ParseBorderStyleSide(CSSParserTokenStream&,
                                     const CSSParserContext&);

CSSValue* ConsumeShadow(CSSParserTokenStream&,
                        const CSSParserContext&,
                        AllowInsetAndSpread);
CSSShadowValue* ParseSingleShadow(CSSParserTokenStream&,
                                  const CSSParserContext&,
                                  AllowInsetAndSpread);

CSSValue* ConsumeColumnCount(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeColumnWidth(CSSParserTokenStream&, const CSSParserContext&);
bool ConsumeColumnWidthOrCount(CSSParserTokenStream&,
                               const CSSParserContext&,
                               CSSValue*&,
                               CSSValue*&);
CSSValue* ConsumeGapLength(CSSParserTokenStream&, const CSSParserContext&);

CSSValue* ConsumeCounter(CSSParserTokenStream&, const CSSParserContext&, int);

CSSValue* ConsumeFontSize(CSSParserTokenStream&,
                          const CSSParserContext&,
                          UnitlessQuirk = UnitlessQuirk::kForbid);

CSSValue* ConsumeLineHeight(CSSParserTokenStream&, const CSSParserContext&);

CSSValue* ConsumeMathDepth(CSSParserTokenStream& stream,
                           const CSSParserContext& context);

CSSValue* ConsumeFontPalette(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumePaletteMixFunction(CSSParserTokenStream&,
                                    const CSSParserContext&);
CSSValueList* ConsumeFontFamily(CSSParserTokenStream&);
CSSValueList* ConsumeNonGenericFamilyNameList(CSSParserTokenStream& stream);
CSSValue* ConsumeGenericFamily(CSSParserTokenStream&);
CSSValue* ConsumeFamilyName(CSSParserTokenStream&);
String ConcatenateFamilyName(CSSParserTokenStream&);
CSSIdentifierValue* ConsumeFontStretchKeywordOnly(CSSParserTokenStream&,
                                                  const CSSParserContext&);
CSSValue* ConsumeFontStretch(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeFontStyle(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeFontWeight(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeFontFeatureSettings(CSSParserTokenStream&,
                                     const CSSParserContext&);
cssvalue::CSSFontFeatureValue* ConsumeFontFeatureTag(CSSParserTokenStream&,
                                                     const CSSParserContext&);
CSSIdentifierValue* ConsumeFontVariantCSS21(CSSParserTokenStream&);
CSSIdentifierValue* ConsumeFontTechIdent(CSSParserTokenStream&);
CSSIdentifierValue* ConsumeFontFormatIdent(CSSParserTokenStream&);
CSSValueID FontFormatToId(String);
bool IsSupportedKeywordTech(CSSValueID keyword);
bool IsSupportedKeywordFormat(CSSValueID keyword);

CSSValue* ConsumeGridLine(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeGridTrackList(CSSParserTokenStream&,
                               const CSSParserContext&,
                               TrackListType);
bool ParseGridTemplateAreasRow(const WTF::String& grid_row_names,
                               NamedGridAreaMap&,
                               const wtf_size_t row_count,
                               wtf_size_t& column_count);
CSSValue* ConsumeGridTemplatesRowsOrColumns(CSSParserTokenStream&,
                                            const CSSParserContext&);
bool ConsumeGridItemPositionShorthand(bool important,
                                      CSSParserTokenStream&,
                                      const CSSParserContext&,
                                      CSSValue*& start_value,
                                      CSSValue*& end_value);
bool ConsumeGridTemplateShorthand(bool important,
                                  CSSParserTokenStream&,
                                  const CSSParserContext&,
                                  const CSSValue*& template_rows,
                                  const CSSValue*& template_columns,
                                  const CSSValue*& template_areas);

CSSValue* ConsumeHyphenateLimitChars(CSSParserTokenStream&,
                                     const CSSParserContext&);

// The fragmentation spec says that page-break-(after|before|inside) are to be
// treated as shorthands for their break-(after|before|inside) counterparts.
// We'll do the same for the non-standard properties
// -webkit-column-break-(after|before|inside).
bool ConsumeFromPageBreakBetween(CSSParserTokenStream&, CSSValueID&);
bool ConsumeFromColumnBreakBetween(CSSParserTokenStream&, CSSValueID&);
bool ConsumeFromColumnOrPageBreakInside(CSSParserTokenStream&, CSSValueID&);

bool ValidWidthOrHeightKeyword(CSSValueID id, const CSSParserContext& context);

CSSValue* ConsumeMaxWidthOrHeight(CSSParserTokenStream&,
                                  const CSSParserContext&,
                                  UnitlessQuirk = UnitlessQuirk::kForbid);
CSSValue* ConsumeWidthOrHeight(CSSParserTokenStream&,
                               const CSSParserContext&,
                               UnitlessQuirk = UnitlessQuirk::kForbid);

CSSValue* ConsumeMarginOrOffset(CSSParserTokenStream&,
                                const CSSParserContext&,
                                UnitlessQuirk,
                                CSSAnchorQueryTypes = kCSSAnchorQueryTypesNone);
CSSValue* ConsumeScrollPadding(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeScrollStart(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeScrollStartTarget(CSSParserTokenStream&);
CSSValue* ConsumeOffsetPath(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumePathOrNone(CSSParserTokenStream&);
CSSValue* ConsumeOffsetRotate(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeInitialLetter(CSSParserTokenStream&, const CSSParserContext&);

CSSValue* ConsumeBasicShape(
    CSSParserTokenStream&,
    const CSSParserContext&,
    AllowPathValue = AllowPathValue::kAllow,
    AllowBasicShapeRectValue = AllowBasicShapeRectValue::kAllow,
    AllowBasicShapeXYWHValue = AllowBasicShapeXYWHValue::kAllow);
bool ConsumeRadii(CSSValue* horizontal_radii[4],
                  CSSValue* vertical_radii[4],
                  CSSParserTokenStream&,
                  const CSSParserContext&,
                  bool use_legacy_parsing);

CSSValue* ConsumeTextDecorationLine(CSSParserTokenStream&);
CSSValue* ConsumeTextBoxEdge(CSSParserTokenStream&);
CSSValue* ConsumeTextBoxTrim(CSSParserTokenStream&);

// Consume the `autospace` production.
// https://drafts.csswg.org/css-text-4/#typedef-autospace
CSSValue* ConsumeAutospace(CSSParserTokenStream&);
// Consume the `spacing-trim` production.
// https://drafts.csswg.org/css-text-4/#typedef-spacing-trim
CSSValue* ConsumeSpacingTrim(CSSParserTokenStream&);

CSSValue* ConsumeTransformValue(CSSParserTokenStream&,
                                const CSSParserContext&,
                                bool use_legacy_parsing);
CSSValue* ConsumeTransformList(CSSParserTokenStream&,
                               const CSSParserContext&,
                               const CSSParserLocalContext&);
CSSValue* ConsumeTransitionProperty(CSSParserTokenStream&,
                                    const CSSParserContext&);
bool IsValidPropertyList(const CSSValueList&);
bool IsValidTransitionBehavior(const CSSValueID&);
bool IsValidTransitionBehaviorList(const CSSValueList&);

CSSValue* ConsumeBorderColorSide(CSSParserTokenStream&,
                                 const CSSParserContext&,
                                 const CSSParserLocalContext&);
CSSValue* ConsumeBorderWidth(CSSParserTokenStream&,
                             const CSSParserContext&,
                             UnitlessQuirk);
CSSValue* ConsumeSVGPaint(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ParseSpacing(CSSParserTokenStream&, const CSSParserContext&);

template <typename T>
  requires std::is_same_v<T, CSSParserTokenStream> ||
           std::is_same_v<T, CSSParserTokenRange>
CSSValue* ConsumeSingleContainerName(T&, const CSSParserContext&);
CSSValue* ConsumeContainerName(CSSParserTokenStream&, const CSSParserContext&);
CSSValue* ConsumeContainerType(CSSParserTokenStream&);

UnitlessQuirk UnitlessUnlessShorthand(const CSSParserLocalContext&);

// https://drafts.csswg.org/css-counter-styles-3/#typedef-counter-style-name
CSSCustomIdentValue* ConsumeCounterStyleName(CSSParserTokenStream&,
                                             const CSSParserContext&);
AtomicString ConsumeCounterStyleNameInPrelude(CSSParserTokenStream&,
                                              const CSSParserContext&);

CSSValue* ConsumeFontSizeAdjust(CSSParserTokenStream&, const CSSParserContext&);

// When parsing a counter style name, it should be ASCII lowercased if it's an
// ASCII case-insensitive match of any predefined counter style name.
bool ShouldLowerCaseCounterStyleNameOnParse(const AtomicString&,
                                            const CSSParserContext&);

// https://drafts.csswg.org/css-anchor-position-1/#typedef-position-area
CSSValue* ConsumePositionArea(CSSParserTokenStream&);

// position-area can take one or two keywords. If the second is omitted, either
// the first is repeated, or the second is span-all. This method returns true if
// the omitted value should be the first one repeated.
bool IsRepeatedPositionAreaValue(CSSValueID value_id);

// Template implementations are at the bottom of the file for readability.

template <typename... emptyBaseCase>
inline bool IdentMatches(CSSValueID id) {}
template <CSSValueID head, CSSValueID... tail>
inline bool IdentMatches(CSSValueID id) {}

template <typename...>
bool IsCustomIdent(CSSValueID id) {}

template <CSSValueID head, CSSValueID... tail>
bool IsCustomIdent(CSSValueID id) {}

template <CSSValueID... names>
CSSIdentifierValue* ConsumeIdent(CSSParserTokenRange& range) {}

template <CSSValueID... names>
CSSIdentifierValue* ConsumeIdent(CSSParserTokenStream& stream) {}

// ConsumeCommaSeparatedList and ConsumeSpaceSeparatedList take a callback
// function to call on each item in the list, followed by the arguments to pass
// to this callback.  The first argument to the callback must be the
// CSSParserTokenStream
template <typename Func, typename... Args>
CSSValueList* ConsumeCommaSeparatedList(Func callback,
                                        CSSParserTokenStream& stream,
                                        Args&&... args) {}

template <typename Func, typename... Args>
CSSValueList* ConsumeSpaceSeparatedList(Func callback,
                                        CSSParserTokenStream& stream,
                                        Args&&... args) {}

template <CSSValueID start, CSSValueID end>
CSSValue* ConsumePositionLonghand(CSSParserTokenStream& range,
                                  const CSSParserContext& context) {}

inline bool AtIdent(const CSSParserToken& token, const char* ident) {}

template <typename T>
bool ConsumeIfIdent(T& range_or_stream, const char* ident) {}

inline bool AtDelimiter(const CSSParserToken& token, UChar c) {}

template <typename T>
bool ConsumeIfDelimiter(T& range_or_stream, UChar c) {}

CORE_EXPORT CSSValue* ConsumeSinglePositionTryFallback(CSSParserTokenStream&,
                                                       const CSSParserContext&);
CSSValue* ConsumePositionTryFallbacks(CSSParserTokenStream&,
                                      const CSSParserContext&);

// If the stream starts with “!important”, consumes it and returns true.
// If the stream is at EOF, returns false.
// If parse error, also returns false, but the stream position is unchanged
// and thus guaranteed to not be at EOF.
//
// The typical usage pattern for this is: Call the function,
// then immediately check stream.AtEnd(). If stream.AtEnd(), then
// the parse succeeded and you can use the return value for whether
// the property is important or not. However, if !stream.AtEnd(),
// there has been a parse error (e.g. random junk that was not
// !important, or !important but with more tokens afterwards).
//
// If allow_important_annotation is false, just consumes whitespace
// and returns false. The same pattern as above holds.
bool MaybeConsumeImportant(CSSParserTokenStream& stream,
                           bool allow_important_annotation);

}  // namespace css_parsing_utils
}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PARSING_UTILS_H_