Skip to content

Commit

Permalink
Add support for last-child, first-of-type, last-of-type pseudoselectors
Browse files Browse the repository at this point in the history
  • Loading branch information
chrishow committed Jan 4, 2024
1 parent c0a0667 commit d4cfcfe
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/Translator.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,30 @@ protected function convertSingleSelector(string $css):string {
);
}
break;

case "last-child":
$prev = count($xpath) - 1;
$xpath[$prev] = '*[last()]/self::' . $xpath[$prev];
break;

case 'first-of-type':
$prev = count($xpath) - 1;
$previous = $xpath[$prev];

if(substr($previous, -1, 1) === "]") {
array_push(
$xpath,
"[1]"
);
}
else {
array_push(
$xpath,
"[1]"
);
}
break;

case "nth-of-type":
if (empty($specifier)) {
continue 3;
Expand All @@ -153,6 +177,25 @@ protected function convertSingleSelector(string $css):string {
);
}
break;

case "last-of-type":
$prev = count($xpath) - 1;
$previous = $xpath[$prev];

if(substr($previous, -1, 1) === "]") {
array_push(
$xpath,
"[last()]"
);
}
else {
array_push(
$xpath,
"[last()]"
);
}
break;

}
break;

Expand Down
85 changes: 85 additions & 0 deletions test/phpunit/TranslatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,91 @@ public function testChild() {
);
}

public function testFirstOfTypeNthOfTypeLastOfType() {
$document = new DOMDocument("1.0", "UTF-8");
$document->loadHTML('<dl>
<dt>gigogne</dt>
<dd>
<dl>
<dt>fusee</dt>
<dd>multistage rocket</dd>
<dt>table</dt>
<dd>nest of tables</dd>
</dl>
</dd>
</dl>');

$xpath = new DOMXPath($document);
$selector = new Translator('dl dt:first-of-type');

$matches = $xpath->query($selector);
self::assertEquals(2, count($matches));
self::assertEquals('gigogne', $matches->item(0)->nodeValue);
self::assertEquals('fusee', $matches->item(1)->nodeValue);

$selector = new Translator('dl dt:nth-of-type(2)');

$matches = $xpath->query($selector);
self::assertEquals(1, count($matches));
self::assertEquals('table', $matches->item(0)->nodeValue);

$selector = new Translator('dl dt:last-of-type');

$matches = $xpath->query($selector);
self::assertEquals(2, count($matches));
self::assertEquals('gigogne', $matches->item(0)->nodeValue);
self::assertEquals('table', $matches->item(1)->nodeValue);
}

public function testFirstNthLastChild() {
$document = new DOMDocument("1.0", "UTF-8");
$document->loadHTML('<div><p>Track & field champions:</p>
<ul>
<li>Adhemar da Silva</li>
<li>Wang Junxia</li>
<li>Wilma Rudolph</li>
<li>Babe Didrikson-Zaharias</li>
<li>Betty Cuthbert</li>
<li>Fanny Blankers-Koen</li>
<li>Florence Griffith-Joyner</li>
</ul></div>
');
$xpath = new DOMXPath($document);

$firstChild = new Translator("li:first-child");
$elements = $xpath->query($firstChild);
self::assertEquals(1, $elements->length);
$element = $elements->item(0);

self::assertEquals("li", strtolower($element->tagName));
self::assertEquals(
'Adhemar da Silva',
$element->nodeValue
);

$nthChild = new Translator("li:nth-child(3)");
$elements = $xpath->query($nthChild);
self::assertEquals(1, $elements->length);
$element = $elements->item(0);

self::assertEquals("li", strtolower($element->tagName));
self::assertEquals(
'Wilma Rudolph',
$element->nodeValue
);

$lastChild = new Translator("li:last-child");
$elements = $xpath->query($lastChild);
self::assertEquals(1, $elements->length);
$element = $elements->item(0);

self::assertEquals("li", strtolower($element->tagName));
self::assertEquals(
'Florence Griffith-Joyner',
$element->nodeValue
);
}

public function testId() {
$document = new DOMDocument("1.0", "UTF-8");
$document->loadHTML(Helper::HTML_SIMPLE);
Expand Down

0 comments on commit d4cfcfe

Please sign in to comment.