libhext: C++ Library Documentation 1.0.13-b24695d
Loading...
Searching...
No Matches
NthChildMatch.h
Go to the documentation of this file.
1// Copyright 2015, 2016 Thomas Trapp
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef HEXT_NTH_CHILD_MATCH_H_INCLUDED
16#define HEXT_NTH_CHILD_MATCH_H_INCLUDED
17
18/// @file
19/// Declares hext::NthChildMatch
20
21#include "hext/Cloneable.h"
22#include "hext/Match.h"
23#include "hext/HtmlTag.h"
24#include "hext/Visibility.h"
25
26#include <utility>
27
28#include <gumbo.h>
29
30
31namespace hext {
32
33
34/// Matches HTML nodes having a certain position within their parent HTML
35/// element.
36///
37/// The intent is to mimic the following CSS pseudo-classes:
38/// nth-child, nth-of-type, nth-last-of-type, first-of-type, last-of-type,
39/// first-child, last-child, nth-last-child, nth-last-of-type
40///
41/// See https://developer.mozilla.org/en-US/docs/Web/CSS/%3Anth-child for a
42/// detailed explanation.
43///
44/// @par Example:
45/// ~~~~~~~~~~~~~
46/// // Assume first, second, third are children of the following <ul> element:
47/// // <ul><li>1</li><li>2</li><li>3</li></ul>
48/// const GumboNode * first = ...;
49/// const GumboNode * second = ...;
50/// const GumboNode * third = ...;
51///
52/// NthChildMatch m_even(2, 0); // :nth-child(2n)
53/// NthChildMatch m_odd (2, 1); // :nth-child(2n+1)
54///
55/// assert(!m_even.matches(first));
56/// assert( m_even.matches(second));
57/// assert(!m_even.matches(third));
58///
59/// assert( m_odd.matches(first));
60/// assert(!m_odd.matches(second));
61/// assert( m_odd.matches(third));
62/// ~~~~~~~~~~~~~
63///
64/// @par last-of-type Example:
65/// ~~~~~~~~~~~~~~~~~~~~~~~~~~
66/// // Assume first, second, third are children of the following <a> element:
67/// // <a>
68/// // <b>1</b>
69/// // <u>2</u>
70/// // <b>3</b>
71/// // </a>
72/// const GumboNode * first = ...;
73/// const GumboNode * second = ...;
74/// const GumboNode * third = ...;
75///
76/// NthChildMatch m_last_of_type(
77/// 0, // no repetition
78/// 1, // last element
79/// NthChildMatch::Last | // count following siblings and
80/// NthChildMatch::OfType // only count elements with
81/// // same tag.
82/// );
83///
84/// assert(!m_last_of_type.matches(first));
85/// assert( m_last_of_type.matches(second));
86/// assert( m_last_of_type.matches(third));
87/// ~~~~~~~~~~~~~~~~~~~~~~~~~~
88class HEXT_PUBLIC NthChildMatch final : public Cloneable<NthChildMatch, Match>
89{
90public:
91 /// NthChildMatch's options.
92 enum Option
93 {
94 /// Count preceding siblings (:nth-child).
95 First = 1 << 1,
96
97 /// Count following siblings (:nth-last-child).
98 Last = 1 << 2,
99
100 /// Only count siblings of the same type (:nth-of-type).
101 OfType = 1 << 3
102 };
103
104 /// Constructs an NthChildMatch with the pattern <step * n + shift>.
105 ///
106 /// @param step: The step of the pattern.
107 /// @param shift: The shift of the pattern.
108 /// @param options: See NthChildMatch::Option.
109 /// Default: Count any preceding HTML element.
111 int shift,
112 Option options = Option::First) noexcept;
113
114 /// Constructs an NthChildMatch with the pattern <step * n + shift>, where
115 /// step and shift is given as a std::pair.
116 ///
117 /// @param step_and_shift: The step and shift of the pattern.
118 /// @param options: See NthChildMatch::Option.
119 /// Default: Count any preceding HTML element.
120 explicit NthChildMatch(std::pair<int, int> step_and_shift,
121 Option options = Option::First) noexcept;
122
123 /// Returns true if HTML node matches pattern <step * n + shift>.
124 ///
125 /// @param node: A pointer to a GumboNode.
126 bool matches(const GumboNode * node) const noexcept override;
127
128private:
129 /// Count preceding siblings of an HTML node.
130 ///
131 /// @param node: A pointer to a GumboNode.
132 /// @param count_tag: If given any value other than HtmlTag::ANY, only count
133 /// siblings having this HtmlTag.
135 int count_preceding_siblings(const GumboNode * node,
136 HtmlTag count_tag) const noexcept;
137
138 /// Count following siblings of an HTML node.
139 ///
140 /// @param node: A pointer to a GumboNode.
141 /// @param count_tag: If given any value other than HtmlTag::ANY, only count
142 /// siblings having this HtmlTag.
144 int count_following_siblings(const GumboNode * node,
145 HtmlTag count_tag) const noexcept;
146
147 /// The step in the pattern <step * n + shift>
148 int step_;
149
150 /// The shift in the pattern <step * n + shift>
151 int shift_;
152
153 /// See NthChildMatch::Option.
154 Option options_;
155};
156
157
158/// Applies Bitwise-OR to NthChildMatch::Option.
161{
162 return static_cast<NthChildMatch::Option>(static_cast<int>(left) |
163 static_cast<int>(right));
164}
165
166
167/// Applies Bitwise-AND to NthChildMatch::Option.
170{
171 return static_cast<NthChildMatch::Option>(static_cast<int>(left) &
172 static_cast<int>(right));
173}
174
175
176} // namespace hext
177
178
179#endif // HEXT_NTH_CHILD_MATCH_H_INCLUDED
180
Defines template hext::Cloneable.
All valid HTML tags.
Declares hext::Match.
Defines HEXT_PUBLIC and HEXT_PRIVATE.
#define HEXT_PRIVATE
Definition Visibility.h:27
#define HEXT_PUBLIC
Definition Visibility.h:26
Curiously recurring template pattern that extends a base class to provide a virtual method Cloneable:...
Definition Cloneable.h:37
Matches HTML nodes having a certain position within their parent HTML element.
NthChildMatch(int step, int shift, Option options=Option::First) noexcept
Constructs an NthChildMatch with the pattern <step * n + shift>.
NthChildMatch(std::pair< int, int > step_and_shift, Option options=Option::First) noexcept
Constructs an NthChildMatch with the pattern <step * n + shift>, where step and shift is given as a s...
Option
NthChildMatch's options.
bool matches(const GumboNode *node) const noexcept override
Returns true if HTML node matches pattern <step * n + shift>.
HtmlTag
An enum containing all valid HTML tags.
Definition HtmlTag.h:31
HEXT_PUBLIC NthChildMatch::Option operator|(NthChildMatch::Option left, NthChildMatch::Option right) noexcept
Applies Bitwise-OR to NthChildMatch::Option.
HEXT_PUBLIC NthChildMatch::Option operator&(NthChildMatch::Option left, NthChildMatch::Option right) noexcept
Applies Bitwise-AND to NthChildMatch::Option.