All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
31 namespace 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 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~
88 class HEXT_PUBLIC NthChildMatch final : public Cloneable<NthChildMatch, Match>
89 {
90 public:
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.
110  NthChildMatch(int step,
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 
128 private:
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.
159 HEXT_PUBLIC inline NthChildMatch::Option
160 operator|(NthChildMatch::Option left, NthChildMatch::Option right) noexcept
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 
HEXT_PUBLIC NthChildMatch::Option operator&(NthChildMatch::Option left, NthChildMatch::Option right) noexcept
Applies Bitwise-AND to NthChildMatch::Option.
Matches HTML nodes having a certain position within their parent HTML element.
Definition: NthChildMatch.h:88
All valid HTML tags.
Option
NthChildMatch's options.
Definition: NthChildMatch.h:92
Defines HEXT_PUBLIC and HEXT_PRIVATE.
#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:36
Declares hext::Match.
#define HEXT_PRIVATE
Definition: Visibility.h:27
Defines template hext::Cloneable.
HtmlTag
An enum containing all valid HTML tags.
Definition: HtmlTag.h:28