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
This commit is contained in:
Alexandre Alapetite authored and GitHub committed 2022-08-18 11:14:40 +02:00
1 parent ea0d924985
commit 2acf3a4dd8
6 files changed
+29 -16

No files matched your search

+1 -3
View File
@@ -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/
+7 -1
View File
@@ -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": {
+2 -2
View File
@@ -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.
+1 -1
View File
@@ -3,4 +3,4 @@ namespace Gt\CssXPath;
use RuntimeException;
class CssXPathException extends RuntimeException {}
class CssXPathException extends RuntimeException {}
@@ -1,4 +1,4 @@
<?php
namespace Gt\CssXPath;
class NotYetImplementedException extends CssXPathException {}
class NotYetImplementedException extends CssXPathException {}
+17 -8
View File
@@ -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+)'
. '/';
@@ -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<int, array<string, string>> $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);