aboutsummaryrefslogtreecommitdiff
path: root/lib/phpgt/cssxpath
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2024-09-06 09:11:37 +0200
committerGravatar GitHub <noreply@github.com> 2024-09-06 09:11:37 +0200
commit9f4f6e9cac6c20257ff496c28a02dd9463c6cdcb (patch)
treeb0e4ed9be545841d30458cfe31b0c0aa4828260f /lib/phpgt/cssxpath
parenta81656c3ed5b8fe0f31794a4fbe0d1a907fca8e8 (diff)
Bump phpgt/cssxpath (#6618)
Includes https://github.com/PhpGt/CssXPath/pull/227 Follow-up of https://github.com/PhpGt/CssXPath/pull/227 for PHP 8.4 Requires PHP 8.0+ Full diff https://github.com/PhpGt/CssXPath/compare/d99d35f7194bac19fb3f8726b70c1bc83de3e931...45f3ac151fc21d459e2515c3aff97cd4bf877bf8
Diffstat (limited to 'lib/phpgt/cssxpath')
-rw-r--r--lib/phpgt/cssxpath/README.md14
-rw-r--r--lib/phpgt/cssxpath/src/Translator.php91
2 files changed, 88 insertions, 17 deletions
diff --git a/lib/phpgt/cssxpath/README.md b/lib/phpgt/cssxpath/README.md
index 8dfeabc42..048547442 100644
--- a/lib/phpgt/cssxpath/README.md
+++ b/lib/phpgt/cssxpath/README.md
@@ -8,10 +8,10 @@ A lightweight and dependency free CSS to XPath translator. This repository is us
<a href="https://github.com/PhpGt/CssXPath/actions" target="_blank">
<img src="https://badge.status.php.gt/cssxpath-build.svg" alt="Build status" />
</a>
-<a href="https://scrutinizer-ci.com/g/PhpGt/CssXPath" target="_blank">
+<a href="https://app.codacy.com/gh/PhpGt/CssXPath" target="_blank">
<img src="https://badge.status.php.gt/cssxpath-quality.svg" alt="Code quality" />
</a>
-<a href="https://scrutinizer-ci.com/g/PhpGt/CssXPath" target="_blank">
+<a href="https://app.codecov.io/gh/PhpGt/CssXPath" target="_blank">
<img src="https://badge.status.php.gt/cssxpath-coverage.svg" alt="Code coverage" />
</a>
<a href="https://packagist.org/packages/PhpGt/CssXPath" target="_blank">
@@ -49,5 +49,15 @@ $xpath = new DOMXPath($document);
$inputElementList = $xpath->query(new Translator("form>label>input");
```
+## Using this library with XML Documents
+
+To correctly work with XML documents, where the attributes are case-sensitive, pass `false` to the `htmlMode` property of the constructor.
+
+```php
+$translator = new Translator("[data-FOO='bar']", htmlMode: false);
+```
+
+It's perhaps worth noting that for XML-style matching to work, you must load the document content with DOMDocument->load/DOMDocument->loadXML instead of DOMDocument->loadHTMLFile/DOMDocument->loadHTML, as the HTML loading methods automatically convert the tags and attribute names to lowercase. This is handled automatically when using [PHP.Gt/Dom][gt-dom].
+
[qsa]: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
[gt-dom]: https://www.php.gt/dom
diff --git a/lib/phpgt/cssxpath/src/Translator.php b/lib/phpgt/cssxpath/src/Translator.php
index 01ed98bc6..7bb11265c 100644
--- a/lib/phpgt/cssxpath/src/Translator.php
+++ b/lib/phpgt/cssxpath/src/Translator.php
@@ -12,7 +12,7 @@ class Translator {
. '|(#(?P<id>[\w-]*))'
. '|(\.(?P<class>[\w-]*))'
. '|(?P<sibling>\s*\+\s*)'
- . "|(\[(?P<attribute>[\w-]*)((?P<attribute_equals>[=~$*]+)(?P<attribute_value>(.+\[\]'?)|[^\]]+))*\])+"
+ . "|(\[(?P<attribute>[\w-]*)((?P<attribute_equals>[=~$|^*]+)(?P<attribute_value>(.+\[\]'?)|[^\]]+))*\])+"
. '|(?P<descendant>\s+)'
. '/';
@@ -20,17 +20,14 @@ class Translator {
const EQUALS_CONTAINS_WORD = "~=";
const EQUALS_ENDS_WITH = "$=";
const EQUALS_CONTAINS = "*=";
- const EQUALS_STARTS_WITH_OR_STARTS_WITH_HYPHENATED = "|=";
+ const EQUALS_OR_STARTS_WITH_HYPHENATED = "|=";
const EQUALS_STARTS_WITH = "^=";
- /** @var string */
- protected $cssSelector;
- /** @var string */
- protected $prefix;
-
- public function __construct(string $cssSelector, string $prefix = ".//") {
- $this->cssSelector = $cssSelector;
- $this->prefix = $prefix;
+ public function __construct(
+ protected string $cssSelector,
+ protected string $prefix = ".//",
+ protected bool $htmlMode = true
+ ) {
}
public function __toString():string {
@@ -70,7 +67,11 @@ class Translator {
switch ($currentThreadItem["type"]) {
case "star":
case "element":
- $xpath []= $currentThreadItem['content'];
+ if($this->htmlMode) {
+ $xpath []= strtolower($currentThreadItem['content']);
+ } else {
+ $xpath []= $currentThreadItem['content'];
+ }
$hasElement = true;
break;
@@ -135,6 +136,30 @@ class Translator {
);
}
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;
@@ -156,6 +181,25 @@ class Translator {
);
}
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;
@@ -197,6 +241,10 @@ class Translator {
$hasElement = true;
}
+ if($this->htmlMode) {
+ $currentThreadItem['content'] = strtolower($currentThreadItem['content']);
+ }
+
/** @var null|array<int, array<string, string>> $detail */
$detail = $currentThreadItem["detail"] ?? null;
$detailType = $detail[0] ?? null;
@@ -244,11 +292,24 @@ class Translator {
);
break;
- case self::EQUALS_STARTS_WITH_OR_STARTS_WITH_HYPHENATED:
- throw new NotYetImplementedException();
+ case self::EQUALS_OR_STARTS_WITH_HYPHENATED:
+ array_push(
+ $xpath,
+ "["
+ . "@{$currentThreadItem['content']}=\"{$valueString}\" or "
+ . "starts-with(@{$currentThreadItem['content']}, \"{$valueString}-\")"
+ . "]"
+ );
+ break;
case self::EQUALS_STARTS_WITH:
- throw new NotYetImplementedException();
+ array_push(
+ $xpath,
+ "[starts-with("
+ . "@{$currentThreadItem['content']}, \"{$valueString}\""
+ . ")]"
+ );
+ break;
case self::EQUALS_ENDS_WITH:
array_push(
@@ -279,7 +340,7 @@ class Translator {
protected function preg_match_collated(
string $regex,
string $string,
- callable $transform = null
+ ?callable $transform = null
):array {
preg_match_all(
$regex,