1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/FlyString.h>
#include <AK/NonnullRefPtrVector.h>
#include <AK/RefCounted.h>
#include <AK/String.h>
#include <AK/Vector.h>
namespace Web::CSS {
using SelectorList = NonnullRefPtrVector<class Selector>;
// This is a <complex-selector> in the spec. https://www.w3.org/TR/selectors-4/#complex
class Selector : public RefCounted<Selector> {
public:
struct SimpleSelector {
enum class Type {
Invalid,
Universal,
TagName,
Id,
Class,
Attribute,
PseudoClass,
PseudoElement,
};
Type type { Type::Invalid };
struct ANPlusBPattern {
int step_size { 0 }; // "A"
int offset = { 0 }; // "B"
static ANPlusBPattern parse(StringView const& args);
String to_string() const
{
return String::formatted("{}n{:+}", step_size, offset);
}
};
struct PseudoClass {
enum class Type {
None,
Link,
Visited,
Hover,
Focus,
FirstChild,
LastChild,
OnlyChild,
Empty,
Root,
FirstOfType,
LastOfType,
NthChild,
NthLastChild,
Disabled,
Enabled,
Checked,
Not,
Active,
};
Type type { Type::None };
// FIXME: We don't need this field on every single SimpleSelector, but it's also annoying to malloc it somewhere.
// Only used when "pseudo_class" is "NthChild" or "NthLastChild".
ANPlusBPattern nth_child_pattern;
SelectorList not_selector {};
};
PseudoClass pseudo_class {};
enum class PseudoElement {
None,
Before,
After,
FirstLine,
FirstLetter,
};
PseudoElement pseudo_element { PseudoElement::None };
FlyString value {};
struct Attribute {
enum class MatchType {
None,
HasAttribute,
ExactValueMatch,
ContainsWord, // [att~=val]
ContainsString, // [att*=val]
StartsWithSegment, // [att|=val]
StartsWithString, // [att^=val]
EndsWithString, // [att$=val]
};
MatchType match_type { MatchType::None };
FlyString name {};
String value {};
};
Attribute attribute {};
};
enum class Combinator {
None,
ImmediateChild, // >
Descendant, // <whitespace>
NextSibling, // +
SubsequentSibling, // ~
Column, // ||
};
struct CompoundSelector {
// Spec-wise, the <combinator> is not part of a <compound-selector>,
// but it is more understandable to put them together.
Combinator combinator { Combinator::None };
Vector<SimpleSelector> simple_selectors;
};
static NonnullRefPtr<Selector> create(Vector<CompoundSelector>&& compound_selectors)
{
return adopt_ref(*new Selector(move(compound_selectors)));
}
~Selector();
Vector<CompoundSelector> const& compound_selectors() const { return m_compound_selectors; }
u32 specificity() const;
private:
explicit Selector(Vector<CompoundSelector>&&);
Vector<CompoundSelector> m_compound_selectors;
};
}
|