Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

csstoxpath

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

csstoxpath - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

36

index.js

@@ -48,3 +48,3 @@ const parser = require('css-what');

if (previous.isNonSiblingAxis && ! token.isTagOrUniversal) {
if (previous.isNonSiblingAxis && ! token.isTagOrUniversal && ! token.isPseudoComment) {
xpath.push('*');

@@ -96,6 +96,14 @@ }

break;
default:
default: {
let {data} = token;
if (token.isPseudoNot) {
filters.push(`not(${subExpression(token.data, {operator: 'or'})})`);
filters.push(`not(${subExpression(data, {operator: 'or'})})`);
}
else if (token.isPseudoComment) {
if (! previous.isAxis) {
commitFilters();
xpath.push('/');
}
xpath.push('comment()' + (data ? `[${data}]` : ''));
}
else {

@@ -105,2 +113,3 @@ filters.push(...resolveAsFilters(token));

break;
}
}

@@ -220,5 +229,9 @@ }

case 'text-contains': // fallthrough
case 'text-contains-case': {
case 'text-contains-case': // fallthrough
case 'text-start': // fallthrough
case 'text-start-case': // fallthrough
case 'text-end': // fallthrough
case 'text-end-case': {
// Normalizing whitespace for all text pseudos.
let elementText = 'normalize-space()';
let text = 'normalize-space()';
let searchText = data.trim();

@@ -229,3 +242,3 @@

let abc = 'abcdefghijklmnopqrstuvwxyz';
elementText = `translate(normalize-space(), '${abc.toUpperCase()}', '${abc}')`;
text = `translate(normalize-space(), '${abc.toUpperCase()}', '${abc}')`;
searchText = searchText.toLowerCase();

@@ -242,6 +255,12 @@ }

let textExpr = `${elementText} = ${searchText}`;
let textExpr = `${text} = ${searchText}`;
if (/contains/.test(name)) {
textExpr = `contains(${elementText}, ${searchText})`;
textExpr = `contains(${text}, ${searchText})`;
}
else if (/^text-start/.test(name)) {
textExpr = `starts-with(${text}, ${searchText})`;
}
else if (/^text-end/.test(name)) {
textExpr = `substring(${text}, string-length(${text})-${searchText.length-3}) = ${searchText}`;
}

@@ -280,2 +299,3 @@ elements.push(textExpr);

token.isNonSiblingAxis = /^(descendant|child)$/.test(type);
token.isAxis = token.isSiblingAxis || token.isNonSiblingAxis;
token.isTagOrUniversal = /^(tag|universal)$/.test(type);

@@ -282,0 +302,0 @@ return token;

{
"name": "csstoxpath",
"version": "1.0.0",
"version": "1.1.0",
"description": "CSS to XPath",

@@ -5,0 +5,0 @@ "main": "index.js",

[![Build Status](https://travis-ci.org/peteboere/csstoxpath.svg?branch=master)](https://travis-ci.org/peteboere/csstoxpath)
## CSS to XPath
# CSS to XPath
Converts most CSS 2.1/3 selectors (see exclusions below) to equivalent XPath.
Converts most CSS 2.1/3 selectors (see exclusions below) to equivalent XPath 1.0 expression.

@@ -10,27 +10,40 @@ See `test.js` for examples.

### Custom pseudo classes
## Custom pseudos
All `:text*` text matching pseudo classes normalize whitespace and ignore tags.
To take advantage of the different capabilities of XPath several custom pseudo selectors have been implemented:
#### `:text`
All text matching pseudo classes normalize whitespace and ignore tags.
E.g. `" my <i>string</i> "` is treated as `"my string"`.
* `:text("foo")` Case-insensitive matching of element text content
* `:text-case("foo")` As `:text` but case-sensitive
* `:text-contains("foo")` Case-insensitive substring matching of element text content
* `:text-contains-case("foo")` As `:text-contains` but case-sensitive
* `:text("foo")` Case-insensitive matching of element text
* `:text-case("foo")` Case-sensitive `:text-case`
* `:text-contains("foo")` Case-insensitive substring matching of element text
* `:text-contains-case("foo")` Case-sensitive `:text-contains`
* `:text-start("foo")` Case-insensitive matching of element starting text
* `:text-start-case("foo")` Case-sensitive `:text-start`
* `:text-end("foo")` Case-insensitive matching of element ending text
* `:text-end-case("foo")` Case-sensitive `:text-end`
#### `:comment`
* `:comment` Select comment nodes
* `:comment(n)` Select comment nodes at child position `n`
Note: Can be combined with `:text` to match based on comment text content. E.g. `p > :comment:text("foo")`
#### `:childless`
* `:childless` As `:empty` but ignoring whitespace
### Unsupported selectors
## Unsupported psuedos
These may be supported at a later date:
* `nth-last-child`
* `:lang()`
* `:nth-last-child`
As far as I'm aware the following cannot be implemented in XPath:
Part-dynamic pseudos are excluded as they can only be partially supported by attribute matching:
* `*-of-type`
The following are excluded as they can only be partially supported (XPath only matches static attributes):
* `:checked`

@@ -40,1 +53,8 @@ * `:disabled`

* `:required`
* `:lang`
The following cannot be implemented in XPath 1.0:
* `:*-of-type`
* States: `:hover`, `:focus`, `:active`, `:visited`, `:target` etc.
* Elements: `::before`, `::after`, `::first-letter` etc.

@@ -1,2 +0,2 @@

/*global describe it*/
/* global describe it */

@@ -8,4 +8,4 @@ const cssToXpath = require('./index');

'Simple',
['a', '//a'],
['*', '//*'],
['a', `//a`],
['*', `//*`],
['#a', `//*[@id = 'a']`],

@@ -128,6 +128,35 @@ ['.a',

':text-start',
[':text-start("foo bar")',
`//*[starts-with(translate(normalize-space(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), "foo bar")]`],
':text-start-case (case sensitive)',
[':text-start-case("foo bar")',
`//*[starts-with(normalize-space(), "foo bar")]`],
':text-end',
[':text-end("foo bar")',
`//*[substring(translate(normalize-space(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), string-length(translate(normalize-space(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))-6) = "foo bar"]`],
':text-end-case (case sensitive)',
[':text-end-case("foo bar")',
`//*[substring(normalize-space(), string-length(normalize-space())-6) = "foo bar"]`],
'Unions',
['a, b', `(//a|//b)`],
[':first-child, .foo',
`(//*[position() = 1]|//*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')])`]
`(//*[position() = 1]|//*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')])`],
'Comments',
[':comment', `//comment()`],
['a :comment', `//a//comment()`],
['a > :comment', `//a/comment()`],
['a:comment', `//a/comment()`],
['a:comment(1)', `//a/comment()[1]`],
['a:comment(1):text("Foo")',
`//a/comment()[1][translate(normalize-space(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = "foo"]`],
['a:comment(1):text-case("Foo")', `//a/comment()[1][normalize-space() = "Foo"]`],
['a:comment:text-contains("Foo")',
`//a/comment()[contains(translate(normalize-space(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), "foo")]`],
['a:comment:text-contains-case("Foo")', `//a/comment()[contains(normalize-space(), "Foo")]`]
];

@@ -187,3 +216,3 @@

let unsupported = [
':nth-last-child(2)',
':nth-last-child(1)',
':nth-of-type',

@@ -190,0 +219,0 @@ ':nth-last-of-type',

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc