From 2acf3a4dd87af5c09fcf513517cb852ff6e909ce Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 18 Aug 2022 11:14:40 +0200 Subject: CssXPath-StarSelector (#4506) * CssXPath-StarSelector Add support for selectors such as `a[href*="example"]` https://developer.mozilla.org/docs/Web/CSS/Attribute_selectors Translated to `.//a[contains(@href,"example")]` Upstream PR: https://github.com/PhpGt/CssXPath/pull/181 * Upstream merged --- lib/.gitignore | 4 +--- lib/composer.json | 8 ++++++- lib/phpgt/cssxpath/README.md | 4 ++-- lib/phpgt/cssxpath/src/CssXPathException.php | 2 +- .../cssxpath/src/NotYetImplementedException.php | 2 +- lib/phpgt/cssxpath/src/Translator.php | 25 +++++++++++++++------- 6 files changed, 29 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/.gitignore b/lib/.gitignore index b599767a7..812bbfe76 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,9 +1,7 @@ autoload.php composer.lock composer/ -phpgt/cssxpath/.github/ -phpgt/cssxpath/.gitignore -phpgt/cssxpath/.scrutinizer.yml +phpgt/cssxpath/.* phpgt/cssxpath/composer.json phpgt/cssxpath/CONTRIBUTING.md phpgt/cssxpath/test/ diff --git a/lib/composer.json b/lib/composer.json index 6fdc90ef4..017adfea6 100644 --- a/lib/composer.json +++ b/lib/composer.json @@ -4,9 +4,15 @@ "type": "project", "homepage": "https://freshrss.org/", "license": "AGPL-3.0", + "repositories": [ + { + "type": "git", + "url": "https://github.com/PhpGt/CssXPath.git" + } + ], "require": { "php": ">=7.0.0", - "phpgt/cssxpath": "v1.1.4", + "phpgt/cssxpath": "dev-master#4fbe420aba3d9e729940107ded4236a835a1a132", "phpmailer/phpmailer": "6.6.0" }, "config": { diff --git a/lib/phpgt/cssxpath/README.md b/lib/phpgt/cssxpath/README.md index 9082c8bbf..8dfeabc42 100644 --- a/lib/phpgt/cssxpath/README.md +++ b/lib/phpgt/cssxpath/README.md @@ -1,5 +1,5 @@ -Translate CSS selectors to XPath queries. -========================================= +Translate CSS selectors to XPath queries +======================================== A lightweight and dependency free CSS to XPath translator. This repository is used to bring modern DOM functionality like [`querySelectorAll()`][qsa] to PHP in the [PHP.Gt/Dom][gt-dom] project. diff --git a/lib/phpgt/cssxpath/src/CssXPathException.php b/lib/phpgt/cssxpath/src/CssXPathException.php index 81ad3ac9d..bd7798243 100644 --- a/lib/phpgt/cssxpath/src/CssXPathException.php +++ b/lib/phpgt/cssxpath/src/CssXPathException.php @@ -3,4 +3,4 @@ namespace Gt\CssXPath; use RuntimeException; -class CssXPathException extends RuntimeException {} \ No newline at end of file +class CssXPathException extends RuntimeException {} diff --git a/lib/phpgt/cssxpath/src/NotYetImplementedException.php b/lib/phpgt/cssxpath/src/NotYetImplementedException.php index 39d12b3bc..70d9492cf 100644 --- a/lib/phpgt/cssxpath/src/NotYetImplementedException.php +++ b/lib/phpgt/cssxpath/src/NotYetImplementedException.php @@ -1,4 +1,4 @@ [\w-]*))' . '|(\.(?P[\w-]*))' . '|(?P\s*\+\s*)' - . "|(\[(?P[\w-]*)((?P[=~$]+)(?P(.+\[\]'?)|[^\]]+))*\])+" + . "|(\[(?P[\w-]*)((?P[=~$*]+)(?P(.+\[\]'?)|[^\]]+))*\])+" . '|(?P\s+)' . '/'; @@ -61,7 +61,7 @@ class Translator { $thread = array_values($thread); $xpath = [$this->prefix]; - $prevType = ""; + $hasElement = false; foreach($thread as $threadKey => $currentThreadItem) { $next = isset($thread[$threadKey + 1]) ? $thread[$threadKey + 1] @@ -71,6 +71,7 @@ class Translator { case "star": case "element": $xpath []= $currentThreadItem['content']; + $hasElement = true; break; case "pseudo": @@ -160,23 +161,26 @@ class Translator { case "child": array_push($xpath, "/"); + $hasElement = false; break; case "id": array_push( $xpath, - ($prevType != "element" ? '*' : '') + ($hasElement ? '' : '*') . "[@id='{$currentThreadItem['content']}']" ); + $hasElement = true; break; case "class": // https://devhints.io/xpath#class-check array_push( $xpath, - (($prevType != "element" && $prevType != "class") ? '*' : '') + ($hasElement ? '' : '*') . "[contains(concat(' ',normalize-space(@class),' '),' {$currentThreadItem['content']} ')]" ); + $hasElement = true; break; case "sibling": @@ -184,11 +188,13 @@ class Translator { $xpath, "/following-sibling::*[1]/self::" ); + $hasElement = false; break; case "attribute": - if(!$prevType) { + if(!$hasElement) { array_push($xpath, "*"); + $hasElement = true; } /** @var null|array> $detail */ @@ -220,7 +226,11 @@ class Translator { break; case self::EQUALS_CONTAINS: - throw new NotYetImplementedException(); + array_push( + $xpath, + "[contains(@{$currentThreadItem['content']},\"{$valueString}\")]" + ); + break; case self::EQUALS_CONTAINS_WORD: array_push( @@ -257,10 +267,9 @@ class Translator { case "descendant": array_push($xpath, "//"); + $hasElement = false; break; } - - $prevType = $currentThreadItem["type"]; } return implode("", $xpath); -- cgit v1.2.3