Bladeren bron

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
Alexandre Alapetite 1 jaar geleden
bovenliggende
commit
9f4f6e9cac
3 gewijzigde bestanden met toevoegingen van 89 en 18 verwijderingen
  1. 1 1
      lib/composer.json
  2. 12 2
      lib/phpgt/cssxpath/README.md
  3. 76 15
      lib/phpgt/cssxpath/src/Translator.php

+ 1 - 1
lib/composer.json

@@ -12,7 +12,7 @@
     ],
     "require": {
         "marienfressinaud/lib_opml": "0.5.1",
-        "phpgt/cssxpath": "dev-master#d99d35f7194bac19fb3f8726b70c1bc83de3e931",
+        "phpgt/cssxpath": "dev-master#45f3ac151fc21d459e2515c3aff97cd4bf877bf8",
         "phpmailer/phpmailer": "6.9.1"
     },
     "config": {

+ 12 - 2
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

+ 76 - 15
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,