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

css2xpath

Package Overview
Dependencies
Maintainers
2
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

css2xpath - npm Package Compare versions

Comparing version 0.0.1 to 0.0.3

test.js

716

index.js
'use strict';
(function () {
var xpath_to_lower = function (s) {
return "translate(" + (s || 'normalize-space()') + ", 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz')";
},
xpath_ends_with = function (s1, s2) {
return 'substring(' + s1 + ',string-length(' + s1 + ')-string-length(' + s2 + ')+1)=' + s2;
},
xpath_url = function (s) {
return 'substring-before(concat(substring-after(' + (s || xpath_url_attrs) + ',"://"),"?"),"?")';
},
xpath_url_path = function (s) {
var xpath_to_lower = function (s) {
return 'translate(' +
(s || 'normalize-space()') +
', \'ABCDEFGHJIKLMNOPQRSTUVWXYZ\'' +
', \'abcdefghjiklmnopqrstuvwxyz\')';
},
xpath_ends_with = function (s1, s2) {
return 'substring(' + s1 + ',' +
'string-length(' + s1 + ')-string-length(' + s2 + ')+1)=' + s2;
},
xpath_url = function (s) {
return 'substring-before(concat(substring-after(' +
(s || xpath_url_attrs) + ',"://"),"?"),"?")';
},
xpath_url_path = function (s) {
return 'substring-after(' + (s || xpath_url_attrs) + ',"/")';
},
},
xpath_url_domain = function (s) {
return 'substring-before(concat(substring-after(' +
(s || xpath_url_attrs) + ',"://"),"/"),"/")';
},
xpath_url_attrs = '@href|@src',
xpath_lower_case = xpath_to_lower(),
xpath_ns_uri = 'ancestor-or-self::*[last()]/@url',
xpath_ns_path = xpath_url_path(xpath_url(xpath_ns_uri)),
xpath_has_protocal = '(starts-with(' + xpath_url_attrs + ',"http://") or starts-with(' + xpath_url_attrs + ',"https://"))',
xpath_is_internal = 'starts-with(' + xpath_url() + ',' + xpath_url_domain(xpath_ns_uri) + ') or ' + xpath_ends_with(xpath_url_domain(), xpath_url_domain(xpath_ns_uri)),
xpath_is_local = '(' + xpath_has_protocal + ' and starts-with(' + xpath_url() + ',' + xpath_url(xpath_ns_uri) + '))',
xpath_is_path = 'starts-with(' + xpath_url_attrs + ',"/")',
xpath_is_local_path = 'starts-with(' + xpath_url_path() + ',' + xpath_ns_path + ')',
xpath_normalize_space = 'normalize-space()',
xpath_internal = '[not(' + xpath_has_protocal + ') or ' + xpath_is_internal + ']',
xpath_external = '[' + xpath_has_protocal + ' and not(' + xpath_is_internal + ')]',
escape_literal = String.fromCharCode(30),
escape_parens = String.fromCharCode(31),
regex_string_literal = /("[^"\x1E]*"|'[^'\x1E]*'|=\s*[^\s\]\'\"]+)/g,
regex_escaped_literal = /['"]?(\x1E+)['"]?/g,
regex_css_wrap_pseudo = /(\x1F\)|[^\)])\:(first|limit|last|gt|lt|eq|nth)([^\-]|$)/,
regex_specal_chars = /[\x1C-\x1F]+/g,
regex_first_axis = /^([\s\(\x1F]*)(\.?[^\.\/\(]{1,2}[a-z]*:*)/,
regex_filter_prefix = /(^|\/|\:)\[/g,
regex_attr_prefix = /([^\(\[\/\|\s\x1F])\@/g,
regex_nth_equation = /^([-0-9]*)n.*?([0-9]*)$/,
css_combinators_regex = /\s*(!?[+>~,^ ])\s*(\.?\/+|[a-z\-]+::)?([a-z\-]+\()?((and\s*|or\s*|mod\s*)?[^+>~,\s'"\]\|\^\$\!\<\=\x1C-\x1F]+)?/g,
css_combinators_callback = function (match, operator, axis, func, literal, exclude, offset, orig) {
var prefix = ''; // If we can, we'll prefix a '.'
xpath_url_domain = function (s) {
return 'substring-before(concat(substring-after(' + (s || xpath_url_attrs) + ',"://"),"/"),"/")';
},
xpath_url_attrs = '@href|@src',
xpath_lower_case = xpath_to_lower(),
xpath_ns_uri = 'ancestor-or-self::*[last()]/@url',
xpath_ns_path = xpath_url_path(xpath_url(xpath_ns_uri)),
xpath_has_protocal = '(starts-with(' + xpath_url_attrs + ',"http://") or starts-with(' + xpath_url_attrs + ',"https://"))',
xpath_is_internal = 'starts-with(' + xpath_url() + ',' + xpath_url_domain(xpath_ns_uri) + ') or ' + xpath_ends_with(xpath_url_domain(), xpath_url_domain(xpath_ns_uri)),
xpath_is_local = '(' + xpath_has_protocal + ' and starts-with(' + xpath_url() + ',' + xpath_url(xpath_ns_uri) + '))',
xpath_is_path = 'starts-with(' + xpath_url_attrs + ',"/")',
xpath_is_local_path = 'starts-with(' + xpath_url_path() + ',' + xpath_ns_path + ')',
xpath_normalize_space = "normalize-space()",
xpath_internal = '[not(' + xpath_has_protocal + ') or ' + xpath_is_internal + ']',
xpath_external = '[' + xpath_has_protocal + ' and not(' + xpath_is_internal + ')]',
escape_literal = String.fromCharCode(30),
escape_parens = String.fromCharCode(31),
regex_string_literal = /("[^"\x1E]*"|'[^'\x1E]*'|=\s*[^\s\]\'\"]+)/g,
regex_escaped_literal = /['"]?(\x1E+)['"]?/g,
regex_css_wrap_pseudo = /(\x1F\)|[^\)])\:(first|limit|last|gt|lt|eq|nth)([^\-]|$)/,
regex_specal_chars = /[\x1C-\x1F]+/g,
regex_first_axis = /^([\s\(\x1F]*)(\.?[^\.\/\(]{1,2}[a-z]*:*)/,
regex_filter_prefix = /(^|\/|\:)\[/g,
regex_attr_prefix = /([^\(\[\/\|\s\x1F])\@/g,
regex_nth_equation = /^([-0-9]*)n.*?([0-9]*)$/,
css_combinators_regex = /\s*(!?[+>~,^ ])\s*(\.?\/+|[a-z\-]+::)?([a-z\-]+\()?((and\s*|or\s*|mod\s*)?[^+>~,\s'"\]\|\*\^\$\!\<\=\x1C-\x1F]+)?/g,
css_combinators_callback = function (match, operator, axis, func, literal, exclude, offset, orig) {
// XPath operators can look like node-name selectors
// Detect false positive for " and", " or", " mod"
if (operator === ' ' && exclude !== undefined) {
return match;
return match;
}
var prefix = ''; // If we can, we'll prefix a '.'
if (axis === undefined) {
// Only allow node-selecting XPath functions
// Detect false positive for " + count(...)", " count(...)", " > position()", etc.
if (func !== undefined && (func !== 'node(' && func !== 'text(' && func !== 'comment('))
return;
else if (literal === undefined)
literal = func; // Handle case " + text()", " > comment()", etc. where "func" is our "literal"
// Only allow node-selecting XPath functions
// Detect false positive for " + count(...)", " count(...)", " > position()", etc.
if (func !== undefined && (func !== 'node(' && func !== 'text(' && func !== 'comment(')) {
return;
} else if (literal === undefined) {
literal = func;
} // Handle case " + text()", " > comment()", etc. where "func" is our "literal"
// XPath math operators match some CSS combinators
// Detect false positive for " + 1", " > 1", etc.
if (isNumeric(literal))
return match;
if (isNumeric(literal)) {
return match;
}
var prevChar = orig.charAt(offset - 1);
var prevChar = orig.charAt(offset - 1);
if (prevChar.length === 0 ||
if (prevChar.length === 0 ||
prevChar === '(' ||
prevChar === '|' ||
prevChar === ':')
prefix = '.';
prevChar === ':') {
prefix = '.';
}
}

@@ -81,6 +84,7 @@

if (literal === undefined) {
if (offset + match.length === orig.length)
literal = '*';
else
return match;
if (offset + match.length === orig.length) {
literal = '*';
} else {
return match;
}
}

@@ -90,33 +94,35 @@

switch (operator) {
case ' ':
return '//' + literal;
case '>':
return '/' + literal;
case '+':
return prefix + '/following-sibling::*[1]/self::' + literal;
case '~':
return prefix + '/following-sibling::' + literal;
case ',':
if (axis === undefined);
axis = './/';
return '|' + axis + literal;
case '^': // first child
return '/child::*[1]/self::' + literal;
case '!^': // last child
return '/child::*[last()]/self::' + literal;
case '! ': // ancestor-or-self
return '/ancestor-or-self::' + literal;
case '!>': // direct parent
return '/parent::' + literal;
case '!+': // adjacent preceding sibling
return '/preceding-sibling::*[1]/self::' + literal;
case '!~': // preceding sibling
return '/preceding-sibling::' + literal;
//case '~~'
// return '/following-sibling::*/self::|'+selectorStart(orig, offset)+'/preceding-sibling::*/self::'+literal;
case ' ':
return '//' + literal;
case '>':
return '/' + literal;
case '+':
return prefix + '/following-sibling::*[1]/self::' + literal;
case '~':
return prefix + '/following-sibling::' + literal;
case ',':
if (axis === undefined) {
}
axis = './/';
return '|' + axis + literal;
case '^': // first child
return '/child::*[1]/self::' + literal;
case '!^': // last child
return '/child::*[last()]/self::' + literal;
case '! ': // ancestor-or-self
return '/ancestor-or-self::' + literal;
case '!>': // direct parent
return '/parent::' + literal;
case '!+': // adjacent preceding sibling
return '/preceding-sibling::*[1]/self::' + literal;
case '!~': // preceding sibling
return '/preceding-sibling::' + literal;
// case '~~'
// return '/following-sibling::*/self::|'+selectorStart(orig, offset)+'/preceding-sibling::*/self::'+literal;
}
},
},
css_attributes_regex = /\[([^\@\|\*\=\^\~\$\!\(\/\s\x1C-\x1F]+)\s*(([\|\*\~\^\$\!]?)=?\s*(\x1E+))?\]/g,
css_attributes_callback = function (str, attr, comp, op, val, offset, orig) {
css_attributes_regex = /\[([^\@\|\*\=\^\~\$\!\(\/\s\x1C-\x1F]+)\s*(([\|\*\~\^\$\!]?)=?\s*(\x1E+))?\]/g,
css_attributes_callback = function (str, attr, comp, op, val, offset, orig) {
var axis = '';

@@ -131,180 +137,191 @@ var prevChar = orig.charAt(offset - 1);

switch (op) {
case '!':
return axis + '[not(@' + attr + ') or @' + attr + '!="' + val + '"]';
case '$':
return axis + '[substring(@' + attr + ',string-length(@' + attr + ')-(string-length("' + val + '")-1))="' + val + '"]';
case '^':
return axis + '[starts-with(@' + attr + ',"' + val + '")]';
case '~':
return axis + '[contains(concat(" ",normalize-space(@' + attr + ')," "),concat(" ","' + val + '"," "))]';
case '*':
return axis + '[contains(@' + attr + ',"' + val + '")]';
case '|':
return axis + '[@' + attr + '="' + val + '" or starts-with(@' + attr + ',concat("' + val + '","-"))]';
default:
if (comp === undefined) {
if (attr.charAt(attr.length - 1) === '(' || attr.search(/^[0-9]+$/) !== -1 || attr.indexOf(':') !== -1)
return str;
return axis + '[@' + attr + ']';
} else {
return axis + '[@' + attr + '="' + val + '"]';
}
case '!':
return axis + '[not(@' + attr + ') or @' + attr + '!="' + val + '"]';
case '$':
return axis + '[substring(@' + attr + ',string-length(@' + attr + ')-(string-length("' + val + '")-1))="' + val + '"]';
case '^':
return axis + '[starts-with(@' + attr + ',"' + val + '")]';
case '~':
return axis + '[contains(concat(" ",normalize-space(@' + attr + ')," "),concat(" ","' + val + '"," "))]';
case '*':
return axis + '[contains(@' + attr + ',"' + val + '")]';
case '|':
return axis + '[@' + attr + '="' + val + '" or starts-with(@' + attr + ',concat("' + val + '","-"))]';
default:
if (comp === undefined) {
if (attr.charAt(attr.length - 1) === '(' || attr.search(/^[0-9]+$/) !== -1 || attr.indexOf(':') !== -1) {
return str;
}
return axis + '[@' + attr + ']';
} else {
return axis + '[@' + attr + '="' + val + '"]';
}
}
},
},
css_pseudo_classes_regex = /:([a-z\-]+)(\((\x1F+)(([^\x1F]+(\3\x1F+)?)*)(\3\)))?/g,
css_pseudo_classes_callback = function (match, name, g1, g2, arg, g3, g4, g5, offset, orig) {
css_pseudo_classes_regex = /:([a-z\-]+)(\((\x1F+)(([^\x1F]+(\3\x1F+)?)*)(\3\)))?/g,
css_pseudo_classes_callback = function (match, name, g1, g2, arg, g3, g4, g5, offset, orig) {
if (orig.charAt(offset - 1) === ':' && orig.charAt(offset - 2) !== ':') {
// XPath "axis::node-name" will match
// Detect false positive ":node-name"
return match;
return match;
}
if (name === 'odd' || name === 'even') {
arg = name;
name = "nth-of-type";
arg = name;
name = 'nth-of-type';
}
switch (name) { // name.toLowerCase()?
case 'after':
return "[count(" + css2xpath('preceding::' + arg, true) + ") > 0]";
case 'after-sibling':
return "[count(" + css2xpath('preceding-sibling::' + arg, true) + ") > 0]";
case 'before':
return "[count(" + css2xpath('following::' + arg, true) + ") > 0]";
case 'before-sibling':
return "[count(" + css2xpath('following-sibling::' + arg, true) + ") > 0]";
case 'checked':
return "[@selected or @checked]";
case 'contains':
return "[contains(" + xpath_normalize_space + "," + arg + ")]";
case 'icontains':
return "[contains(" + xpath_lower_case + "," + xpath_to_lower(arg) + ")]";
case 'empty':
return "[not(*) and not(normalize-space())]";
case 'enabled':
case 'disabled':
return "[@" + name + "]";
case 'first-child':
return "[not(preceding-sibling::*)]";
case 'first':
case 'limit':
case 'first-of-type':
if (arg !== undefined)
return '[position()<=' + arg + ']';
return '[1]';
case 'gt':
case 'after':
return '[count(' + css2xpath('preceding::' + arg, true) + ') > 0]';
case 'after-sibling':
return '[count(' + css2xpath('preceding-sibling::' + arg, true) + ') > 0]';
case 'before':
return '[count(' + css2xpath('following::' + arg, true) + ') > 0]';
case 'before-sibling':
return '[count(' + css2xpath('following-sibling::' + arg, true) + ') > 0]';
case 'checked':
return '[@selected or @checked]';
case 'contains':
return '[contains(' + xpath_normalize_space + ',' + arg + ')]';
case 'icontains':
return '[contains(' + xpath_lower_case + ',' + xpath_to_lower(arg) + ')]';
case 'empty':
return '[not(*) and not(normalize-space())]';
case 'enabled':
case 'disabled':
return '[@' + name + ']';
case 'first-child':
return '[not(preceding-sibling::*)]';
case 'first':
case 'limit':
case 'first-of-type':
if (arg !== undefined) {
return '[position()<=' + arg + ']';
}
return '[1]';
case 'gt':
// Position starts at 0 for consistency with Sizzle selectors
return '[position()>' + (parseInt(arg, 10) + 1) + ']';
case 'lt':
return '[position()>' + (parseInt(arg, 10) + 1) + ']';
case 'lt':
// Position starts at 0 for consistency with Sizzle selectors
return '[position()<' + (parseInt(arg, 10) + 1) + ']';
case 'last-child':
return "[not(following-sibling::*)]";
case 'only-child':
return "[not(preceding-sibling::*) and not(following-sibling::*)]";
case 'only-of-type':
return "[not(preceding-sibling::*[name()=name(self::node())]) and not(following-sibling::*[name()=name(self::node())])]";
case 'nth-child':
if (isNumeric(arg))
return '[(count(preceding-sibling::*)+1) = ' + arg + ']';
switch (arg) {
case "even":
return "[(count(preceding-sibling::*)+1) mod 2=0]";
case "odd":
return "[(count(preceding-sibling::*)+1) mod 2=1]";
default:
var a = (arg || "0").replace(regex_nth_equation, "$1+$2").split("+");
return '[position()<' + (parseInt(arg, 10) + 1) + ']';
case 'last-child':
return '[not(following-sibling::*)]';
case 'only-child':
return '[not(preceding-sibling::*) and not(following-sibling::*)]';
case 'only-of-type':
return '[not(preceding-sibling::*[name()=name(self::node())]) and not(following-sibling::*[name()=name(self::node())])]';
case 'nth-child':
if (isNumeric(arg)) {
return '[(count(preceding-sibling::*)+1) = ' + arg + ']';
}
switch (arg) {
case 'even':
return '[(count(preceding-sibling::*)+1) mod 2=0]';
case 'odd':
return '[(count(preceding-sibling::*)+1) mod 2=1]';
default:
var a = (arg || '0').replace(regex_nth_equation, '$1+$2').split('+');
a[0] = a[0] || "1";
a[1] = a[1] || "0";
return "[(count(preceding-sibling::*)+1)>=" + a[1] + " and ((count(preceding-sibling::*)+1)-" + a[1] + ") mod " + a[0] + "=0]";
}
case 'nth-of-type':
if (isNumeric(arg))
return '[' + arg + ']';
switch (arg) {
case "odd":
return "[position() mod 2=1]";
case "even":
return "[position() mod 2=0 and position()>=0]";
default:
var a = (arg || "0").replace(regex_nth_equation, "$1+$2").split("+");
a[0] = a[0] || '1';
a[1] = a[1] || '0';
return '[(count(preceding-sibling::*)+1)>=' + a[1] + ' and ((count(preceding-sibling::*)+1)-' + a[1] + ') mod ' + a[0] + '=0]';
}
case 'nth-of-type':
if (isNumeric(arg)) {
return '[' + arg + ']';
}
switch (arg) {
case 'odd':
return '[position() mod 2=1]';
case 'even':
return '[position() mod 2=0 and position()>=0]';
default:
var a = (arg || '0').replace(regex_nth_equation, '$1+$2').split('+');
a[0] = a[0] || "1";
a[1] = a[1] || "0";
return "[position()>=" + a[1] + " and (position()-" + a[1] + ") mod " + a[0] + "=0]";
}
case 'eq':
case 'nth':
// Position starts at 0 for consistency with Sizzle selectors
return '[' + (parseInt(arg, 10) + 1) + ']';
case 'text':
return '[@type="text"]';
case 'istarts-with':
return "[starts-with(" + xpath_lower_case + ',' + xpath_to_lower(arg) + ')]';
case 'starts-with':
return "[starts-with(" + xpath_normalize_space + ',' + arg + ')]';
case 'iends-with':
return "[" + xpath_ends_with(xpath_lower_case, xpath_to_lower(arg)) + "]";
case 'ends-with':
return "[" + xpath_ends_with(xpath_normalize_space, arg) + "]";
case 'has':
var xpath = prependAxis(css2xpath(arg, true), './/');
a[0] = a[0] || '1';
a[1] = a[1] || '0';
return '[position()>=' + a[1] + ' and (position()-' + a[1] + ') mod ' + a[0] + '=0]';
}
case 'eq':
case 'nth':
// Position starts at 0 for consistency with Sizzle selectors
if (isNumeric(arg)) {
return '[' + (parseInt(arg, 10) + 1) + ']';
}
return "[count(" + xpath + ") > 0]";
case 'has-sibling':
var xpath = css2xpath('preceding-sibling::' + arg, true);
return '[1]';
case 'text':
return '[@type="text"]';
case 'istarts-with':
return '[starts-with(' + xpath_lower_case + ',' + xpath_to_lower(arg) + ')]';
case 'starts-with':
return '[starts-with(' + xpath_normalize_space + ',' + arg + ')]';
case 'iends-with':
return '[' + xpath_ends_with(xpath_lower_case, xpath_to_lower(arg)) + ']';
case 'ends-with':
return '[' + xpath_ends_with(xpath_normalize_space, arg) + ']';
case 'has':
var xpath = prependAxis(css2xpath(arg, true), './/');
return "[count(" + xpath + ") > 0 or count(following-sibling::" + xpath.substr(19) + ") > 0]";
case 'has-parent':
return "[count(" + css2xpath('parent::' + arg, true) + ") > 0]";
case 'has-ancestor':
return "[count(" + css2xpath('ancestor::' + arg, true) + ") > 0]";
case 'last':
case 'last-of-type':
if (arg !== undefined)
return "[position()>last()-" + arg + "]";
return "[last()]";
case 'selected': // Sizzle: "(option) elements that are currently selected"
return "[local-name()=\"option\" and @selected]";
case 'skip':
case 'skip-first':
return "[position()>" + arg + "]";
case 'skip-last':
if (arg !== undefined)
return "[last()-position()>=" + arg + "]";
return "[position()<last()]";
case 'root':
return "/ancestor::[last()]";
case 'range':
var arr = arg.split(',');
return '[count(' + xpath + ') > 0]';
case 'has-sibling':
var xpath = css2xpath('preceding-sibling::' + arg, true);
return "[" + arr[0] + "<=position() and position()<=" + arr[1] + "]";
case 'input': // Sizzle: "input, button, select, and textarea are all considered to be input elements."
return '[local-name()="input" or local-name()="button" or local-name()="select" or local-name()="textarea"]';
case 'internal':
return xpath_internal;
case 'external':
return xpath_external;
case 'http':
case 'https':
case 'mailto':
case 'javascript':
return '[starts-with(@href,concat("' + name + '",":"))]';
case 'domain':
return '[(string-length(' + xpath_url_domain() + ')=0 and contains(' + xpath_url_domain(xpath_ns_uri) + ',' + arg + ')) or contains(' + xpath_url_domain() + ',' + arg + ')]';
case 'path':
return '[starts-with(' + xpath_url_path() + ',substring-after("' + arg + '","/"))]'
case 'not':
var xpath = css2xpath(arg, true);
return '[count(' + xpath + ') > 0 or count(following-sibling::' + xpath.substr(19) + ') > 0]';
case 'has-parent':
return '[count(' + css2xpath('parent::' + arg, true) + ') > 0]';
case 'has-ancestor':
return '[count(' + css2xpath('ancestor::' + arg, true) + ') > 0]';
case 'last':
case 'last-of-type':
if (arg !== undefined) {
return '[position()>last()-' + arg + ']';
}
return '[last()]';
case 'selected': // Sizzle: "(option) elements that are currently selected"
return '[local-name()="option" and @selected]';
case 'skip':
case 'skip-first':
return '[position()>' + arg + ']';
case 'skip-last':
if (arg !== undefined) {
return '[last()-position()>=' + arg + ']';
}
return '[position()<last()]';
case 'root':
return '/ancestor::[last()]';
case 'range':
var arr = arg.split(',');
if (xpath.charAt(0) === '[')
xpath = 'self::node()' + xpath;
return '[not(' + xpath + ')]';
case 'target':
return '[starts-with(@href, "#")]';
case 'root':
return 'ancestor-or-self::*[last()]';
/*case 'active':
return '[' + arr[0] + '<=position() and position()<=' + arr[1] + ']';
case 'input': // Sizzle: "input, button, select, and textarea are all considered to be input elements."
return '[local-name()="input" or local-name()="button" or local-name()="select" or local-name()="textarea"]';
case 'internal':
return xpath_internal;
case 'external':
return xpath_external;
case 'http':
case 'https':
case 'mailto':
case 'javascript':
return '[starts-with(@href,concat("' + name + '",":"))]';
case 'domain':
return '[(string-length(' + xpath_url_domain() + ')=0 and contains(' + xpath_url_domain(xpath_ns_uri) + ',' + arg + ')) or contains(' + xpath_url_domain() + ',' + arg + ')]';
case 'path':
return '[starts-with(' + xpath_url_path() + ',substring-after("' + arg + '","/"))]'
case 'not':
var xpath = css2xpath(arg, true);
if (xpath.charAt(0) === '[') {
xpath = 'self::node()' + xpath;
}
return '[not(' + xpath + ')]';
case 'target':
return '[starts-with(@href, "#")]';
case 'root':
return 'ancestor-or-self::*[last()]';
/* case 'active':
case 'focus':

@@ -315,21 +332,21 @@ case 'hover':

return '';*/
case 'lang':
return '[@lang="' + arg + '"]';
case 'read-only':
case 'read-write':
return '[@' + name.replace('-', '') + ']';
case 'valid':
case 'required':
case 'in-range':
case 'out-of-range':
return '[@' + name + ']';
default:
return str;
case 'lang':
return '[@lang="' + arg + '"]';
case 'read-only':
case 'read-write':
return '[@' + name.replace('-', '') + ']';
case 'valid':
case 'required':
case 'in-range':
case 'out-of-range':
return '[@' + name + ']';
default:
return match;
}
},
},
css_ids_classes_regex = /(#|\.)([^\#\@\.\/\(\[\)\]\|\:\s\+\>\<\'\"\x1D-\x1F]+)/g,
css_ids_classes_callback = function (str, op, val, offset, orig) {
css_ids_classes_regex = /(#|\.)([^\#\@\.\/\(\[\)\]\|\:\s\+\>\<\'\"\x1D-\x1F]+)/g,
css_ids_classes_callback = function (str, op, val, offset, orig) {
var axis = '';
/*var prevChar = orig.charAt(offset-1);
/* var prevChar = orig.charAt(offset-1);
if (prevChar.length === 0 ||

@@ -341,23 +358,27 @@ prevChar === '/' ||

axis = 'node()';*/
if (op === '#')
return axis + '[@id="' + val + '"]';
if (op === '#') {
return axis + '[@id="' + val + '"]';
}
return axis + '[contains(concat(" ",normalize-space(@class)," ")," ' + val + ' ")]';
};
};
// Prepend descendant-or-self if no other axis is specified
function prependAxis(s, axis) {
function prependAxis(s, axis) {
return s.replace(regex_first_axis, function (match, start, literal) {
if (literal.substr(literal.length - 2) === '::') // Already has axis::
return match;
if (literal.substr(literal.length - 2) === '::') // Already has axis::
{
return match;
}
if (literal.charAt(0) === '[')
axis += '*';
//else if (axis.charAt(axis.length-1) === ')')
if (literal.charAt(0) === '[') {
axis += '*';
}
// else if (axis.charAt(axis.length-1) === ')')
// axis += '/';
return start + axis + literal;
return start + axis + literal;
});
}
}
// Find the begining of the selector, starting at i and working backwards
function selectorStart(s, i) {
function selectorStart(s, i) {
var depth = 0;

@@ -367,54 +388,57 @@ var offset = 0;

while (i--) {
switch (s.charAt(i)) {
case ' ':
case escape_parens:
offset++;
break;
case '[':
case '(':
depth--;
switch (s.charAt(i)) {
case ' ':
case escape_parens:
offset++;
break;
case '[':
case '(':
depth--;
if (depth < 0)
return ++i + offset;
break;
case ']':
case ')':
depth++;
break;
case ',':
case '|':
if (depth === 0)
return ++i + offset;
default:
offset = 0;
if (depth < 0) {
return ++i + offset;
}
break;
case ']':
case ')':
depth++;
break;
case ',':
case '|':
if (depth === 0) {
return ++i + offset;
}
default:
offset = 0;
}
}
return 0;
}
}
// Check if string is numeric
function isNumeric(s) {
function isNumeric(s) {
var num = parseInt(s, 10);
return (!isNaN(num) && '' + num === s);
}
}
// Append escape "char" to "open" or "close"
function escapeChar(s, open, close, char) {
function escapeChar(s, open, close, char) {
var depth = 0;
return s.replace(new RegExp('[\\' + open + '\\' + close + ']', 'g'), function (a) {
if (a === open)
depth++;
if (a === open) {
depth++;
}
if (a === open) {
return a + repeat(char, depth);
} else {
return repeat(char, depth--) + a;
}
if (a === open) {
return a + repeat(char, depth);
} else {
return repeat(char, depth--) + a;
}
})
}
}
function repeat(str, num) {
function repeat(str, num) {
num = Number(num);

@@ -424,24 +448,27 @@ var result = '';

while (true) {
if (num & 1)
result += str;
num >>>= 1;
if (num & 1) {
result += str;
}
num >>>= 1;
if (num <= 0) break;
str += str;
if (num <= 0) {
break;
}
str += str;
}
return result;
}
}
function css2xpath(s, nested) {
//s = s.trim();
function css2xpath(s, nested) {
// s = s.trim();
if (nested === true) {
// Replace :pseudo-classes
s = s.replace(css_pseudo_classes_regex, css_pseudo_classes_callback);
s = s.replace(css_pseudo_classes_regex, css_pseudo_classes_callback);
// Replace #ids and .classes
s = s.replace(css_ids_classes_regex, css_ids_classes_callback);
s = s.replace(css_ids_classes_regex, css_ids_classes_callback);
return s;
return s;
}

@@ -456,12 +483,13 @@

s = s.replace(regex_string_literal, function (s, a) {
if (a.charAt(0) === '=') {
a = a.substr(1).trim();
if (a.charAt(0) === '=') {
a = a.substr(1).trim();
if (isNumeric(a))
return s;
} else {
a = a.substr(1, a.length - 2);
if (isNumeric(a)) {
return s;
}
} else {
a = a.substr(1, a.length - 2);
}
return repeat(escape_literal, literals.push(a));
return repeat(escape_literal, literals.push(a));
});

@@ -477,9 +505,11 @@

while (true) {
var index = s.search(regex_css_wrap_pseudo);
var index = s.search(regex_css_wrap_pseudo);
if (index === -1) break;
index = s.indexOf(':', index);
var start = selectorStart(s, index);
if (index === -1) {
break;
}
index = s.indexOf(':', index);
var start = selectorStart(s, index);
s = s.substr(0, start) +
s = s.substr(0, start) +
'(' + s.substring(start, index) + ')' +

@@ -497,5 +527,5 @@ s.substr(index);

s = s.replace(regex_escaped_literal, function (s, a) {
var str = literals[a.length - 1];
var str = literals[a.length - 1];
return '"' + str + '"';
return '"' + str + '"';
})

@@ -521,11 +551,11 @@

return s;
}
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = css2xpath;
} else {
window.css2xpath = css2xpath;
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = css2xpath;
} else {
window.css2xpath = css2xpath;
}
})();
{
"name": "css2xpath",
"version": "0.0.1",
"version": "0.0.3",
"description": "Advanced CSS to XPath converter",

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

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