Skip to content

Commit 27a8a61

Browse files
committed
Implemented + and ~ operators support
1 parent c58c718 commit 27a8a61

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

src/PHPHtmlParser/Selector/Parser.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function parseSelectorString(string $selector): ParsedSelectorCollectionD
4343
$isNthOfType = false;
4444

4545
// check for elements that alter the behavior of the next element
46-
if ($tag == '>') {
46+
if ($tag == '>' || $tag == '+' || $tag == '~') {
4747
$alterNext = true;
4848
}
4949

src/PHPHtmlParser/Selector/Seeker.php

+16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ class Seeker implements SeekerInterface
2525
public function seek(array $nodes, RuleDTO $rule, array $options): array
2626
{
2727

28+
if ($rule->getTag() == '+' || $rule->getTag() == '~') {
29+
$result = [];
30+
foreach ($nodes as $node) {
31+
if ($rule->getTag() == '+') {
32+
$result[] = $node->nextSibling();
33+
} else {
34+
while ($node->hasNextSibling()) {
35+
$result[] = $node->nextSibling();
36+
$node = $node->nextSibling();
37+
}
38+
}
39+
}
40+
41+
return $result;
42+
}
43+
2844
$options = $this->flattenOptions($options);
2945

3046
$return = [];

src/PHPHtmlParser/Selector/Selector.php

+5
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,19 @@ public function find(AbstractNode $node): Collection
7070
}
7171

7272
$options = [];
73+
$lastRule = null;
7374
foreach ($selector->getRules() as $rule) {
75+
if ($rule->getTag() == '*' && $lastRule && ($lastRule->getTag() == '+' || $lastRule->getTag() == '~')) {
76+
continue;
77+
}
7478
if ($rule->isAlterNext() && $rule->getTag() == '>') {
7579
$options[] = $this->alterNext($rule);
7680
continue;
7781
}
7882
$nodes = $this->seeker->seek($nodes, $rule, $options);
7983
// clear the options
8084
$options = [];
85+
$lastRule = $rule;
8186
}
8287

8388
// this is the final set of nodes

tests/Selector/SeekerTest.php

+78
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,82 @@ public function testSeekNthOfType()
119119
$this->assertEquals('p', $results[0]->getTag()->name());
120120
$this->assertTrue($results[0] === $test->lastChild());
121121
}
122+
123+
public function testSeekNextOne()
124+
{
125+
$ruleDTO = RuleDTO::makeFromPrimitives(
126+
'+',
127+
'=',
128+
null,
129+
null,
130+
false,
131+
false
132+
);
133+
134+
$test = new HtmlNode('div');
135+
$p1 = new HtmlNode('p');
136+
$div = new HtmlNode('div');
137+
$p2 = new HtmlNode('p');
138+
$test->addChild($p1);
139+
$test->addChild($div);
140+
$test->addChild($p2);
141+
142+
$seeker = new Seeker();
143+
144+
$results = $seeker->seek([$p1], $ruleDTO, []);
145+
$this->assertCount(1, $results);
146+
$this->assertEquals('div', $results[0]->getTag()->name());
147+
148+
$ruleDTO = RuleDTO::makeFromPrimitives(
149+
'+',
150+
'=',
151+
null,
152+
null,
153+
false,
154+
false
155+
);
156+
157+
$results = $seeker->seek([$div], $ruleDTO, []);
158+
$this->assertCount(1, $results);
159+
$this->assertEquals('p', $results[0]->getTag()->name());
160+
}
161+
162+
public function testSeekNextAll()
163+
{
164+
$ruleDTO = RuleDTO::makeFromPrimitives(
165+
'~',
166+
'=',
167+
null,
168+
null,
169+
false,
170+
false
171+
);
172+
173+
$test = new HtmlNode('div');
174+
$p1 = new HtmlNode('p');
175+
$div = new HtmlNode('div');
176+
$p2 = new HtmlNode('p');
177+
$test->addChild($p1);
178+
$test->addChild($div);
179+
$test->addChild($p2);
180+
181+
$seeker = new Seeker();
182+
183+
$results = $seeker->seek([$p1], $ruleDTO, []);
184+
$this->assertCount(2, $results);
185+
$this->assertEquals('p', $results[1]->getTag()->name());
186+
187+
$ruleDTO = RuleDTO::makeFromPrimitives(
188+
'~',
189+
'=',
190+
null,
191+
null,
192+
false,
193+
false
194+
);
195+
196+
$results = $seeker->seek([$div], $ruleDTO, []);
197+
$this->assertCount(1, $results);
198+
$this->assertEquals('p', $results[0]->getTag()->name());
199+
}
122200
}

0 commit comments

Comments
 (0)