Socket
Socket
Sign inDemoInstall

css-what

Package Overview
Dependencies
0
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.4.2 to 4.0.0

36

lib/parse.d.ts

@@ -1,5 +0,16 @@

export default parse;
export interface Options {
/**
* When false, tag names will not be lowercased.
* @default true
*/
lowerCaseAttributeNames?: boolean;
/**
* When false, attribute names will not be lowercased.
* @default true
*/
lowerCaseTags?: boolean;
/**
* When `true`, `xmlMode` implies both `lowerCaseTags` and `lowerCaseAttributeNames` are set to `false`.
* @default false
*/
xmlMode?: boolean;

@@ -14,2 +25,3 @@ }

ignoreCase: boolean;
namespace: string | null;
}

@@ -29,5 +41,7 @@ declare type DataType = Selector[][] | null | string;

name: string;
namespace: string | null;
}
export interface UniversalSelector {
type: "universal";
namespace: string | null;
}

@@ -39,3 +53,21 @@ export interface Traversal {

export declare type TraversalType = "adjacent" | "child" | "descendant" | "parent" | "sibling";
declare function parse(selector: string, options?: Options): Selector[][];
/**
* Checks whether a specific selector is a traversal.
* This is useful eg. in swapping the order of elements that
* are not traversals.
*
* @param selector Selector to check.
*/
export declare function isTraversal(selector: Selector): selector is Traversal;
/**
* Parses `selector`, optionally with the passed `options`.
*
* @param selector Selector to parse.
* @param options Options for parsing.
* @returns Returns a two-dimensional array.
* The first dimension represents selectors separated by commas (eg. `sub1, sub2`),
* the second contains the relevant tokens for that selector.
*/
export default function parse(selector: string, options?: Options): Selector[][];
export {};
//# sourceMappingURL=parse.d.ts.map

201

lib/parse.js
"use strict";
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = parse;
var reName = /^[^\\]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
exports.isTraversal = void 0;
var reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
var reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
// Modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
var reAttr = /^\s*((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:(\S?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\3|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*(i)?\]/;
var reAttr = /^\s*(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:(\S?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*([iI])?\]/;
var actionTypes = {

@@ -37,2 +44,16 @@ undefined: "exists",

]);
var traversalNames = new Set(__spreadArrays([
"descendant"
], Object.keys(Traversals).map(function (k) { return Traversals[k]; })));
/**
* Checks whether a specific selector is a traversal.
* This is useful eg. in swapping the order of elements that
* are not traversals.
*
* @param selector Selector to check.
*/
function isTraversal(selector) {
return traversalNames.has(selector.type);
}
exports.isTraversal = isTraversal;
var stripQuotesFromPseudos = new Set(["contains", "icontains"]);

@@ -58,11 +79,21 @@ var quotes = new Set(['"', "'"]);

}
/**
* Parses `selector`, optionally with the passed `options`.
*
* @param selector Selector to parse.
* @param options Options for parsing.
* @returns Returns a two-dimensional array.
* The first dimension represents selectors separated by commas (eg. `sub1, sub2`),
* the second contains the relevant tokens for that selector.
*/
function parse(selector, options) {
var subselects = [];
selector = parseSelector(subselects, "" + selector, options);
if (selector !== "") {
throw new Error("Unmatched selector: " + selector);
var endIndex = parseSelector(subselects, "" + selector, options, 0);
if (endIndex < selector.length) {
throw new Error("Unmatched selector: " + selector.slice(endIndex));
}
return subselects;
}
function parseSelector(subselects, selector, options) {
exports.default = parse;
function parseSelector(subselects, selector, options, selectorIndex) {
var _a, _b;

@@ -72,15 +103,15 @@ if (options === void 0) { options = {}; }

var sawWS = false;
function getName() {
var match = selector.match(reName);
function getName(offset) {
var match = selector.slice(selectorIndex + offset).match(reName);
if (!match) {
throw new Error("Expected name, found " + selector);
throw new Error("Expected name, found " + selector.slice(selectorIndex));
}
var sub = match[0];
selector = selector.substr(sub.length);
return unescapeCSS(sub);
var name = match[0];
selectorIndex += offset + name.length;
return unescapeCSS(name);
}
function stripWhitespace(start) {
while (isWhitespace(selector.charAt(start)))
start++;
selector = selector.substr(start);
function stripWhitespace(offset) {
while (isWhitespace(selector.charAt(selectorIndex + offset)))
offset++;
selectorIndex += offset;
}

@@ -93,5 +124,10 @@ function isEscaped(pos) {

}
function ensureNotTraversal() {
if (tokens.length > 0 && isTraversal(tokens[tokens.length - 1])) {
throw new Error("Did not expect successive traversals.");
}
}
stripWhitespace(0);
while (selector !== "") {
var firstChar = selector.charAt(0);
var firstChar = selector.charAt(selectorIndex);
if (isWhitespace(firstChar)) {

@@ -102,2 +138,3 @@ sawWS = true;

else if (firstChar in Traversals) {
ensureNotTraversal();
tokens.push({ type: Traversals[firstChar] });

@@ -118,14 +155,8 @@ sawWS = false;

if (sawWS) {
if (tokens.length > 0) {
tokens.push({ type: "descendant" });
}
ensureNotTraversal();
tokens.push({ type: "descendant" });
sawWS = false;
}
if (firstChar === "*") {
selector = selector.substr(1);
tokens.push({ type: "universal" });
}
else if (firstChar in attribSelectors) {
if (firstChar in attribSelectors) {
var _c = attribSelectors[firstChar], name_1 = _c[0], action = _c[1];
selector = selector.substr(1);
tokens.push({

@@ -135,14 +166,16 @@ type: "attribute",

action: action,
value: getName(),
value: getName(1),
ignoreCase: false,
namespace: null,
});
}
else if (firstChar === "[") {
selector = selector.substr(1);
var attributeMatch = selector.match(reAttr);
var attributeMatch = selector
.slice(selectorIndex + 1)
.match(reAttr);
if (!attributeMatch) {
throw new Error("Malformed attribute selector: " + selector);
throw new Error("Malformed attribute selector: " + selector.slice(selectorIndex));
}
var completeSelector = attributeMatch[0], baseName = attributeMatch[1], actionType = attributeMatch[2], _d = attributeMatch[4], quotedValue = _d === void 0 ? "" : _d, _e = attributeMatch[5], value = _e === void 0 ? quotedValue : _e, ignoreCase = attributeMatch[6];
selector = selector.substr(completeSelector.length);
var completeSelector = attributeMatch[0], _d = attributeMatch[1], namespace = _d === void 0 ? null : _d, baseName = attributeMatch[2], actionType = attributeMatch[3], _e = attributeMatch[5], quotedValue = _e === void 0 ? "" : _e, _f = attributeMatch[6], value = _f === void 0 ? quotedValue : _f, ignoreCase = attributeMatch[7];
selectorIndex += completeSelector.length + 1;
var name_2 = unescapeCSS(baseName);

@@ -157,2 +190,3 @@ if ((_a = options.lowerCaseAttributeNames) !== null && _a !== void 0 ? _a : !options.xmlMode) {

value: unescapeCSS(value),
namespace: namespace,
ignoreCase: !!ignoreCase,

@@ -162,43 +196,34 @@ });

else if (firstChar === ":") {
if (selector.charAt(1) === ":") {
selector = selector.substr(2);
if (selector.charAt(selectorIndex + 1) === ":") {
tokens.push({
type: "pseudo-element",
name: getName().toLowerCase(),
name: getName(2).toLowerCase(),
});
continue;
}
selector = selector.substr(1);
var name_3 = getName().toLowerCase();
var name_3 = getName(1).toLowerCase();
var data = null;
if (selector.startsWith("(")) {
if (selector.charAt(selectorIndex) === "(") {
if (unpackPseudos.has(name_3)) {
var quot = selector.charAt(1);
var quoted = quotes.has(quot);
selector = selector.substr(quoted ? 2 : 1);
if (quotes.has(selector.charAt(selectorIndex + 1))) {
throw new Error("Pseudo-selector " + name_3 + " cannot be quoted");
}
data = [];
selector = parseSelector(data, selector, options);
if (quoted) {
if (!selector.startsWith(quot)) {
throw new Error("Unmatched quotes in :" + name_3);
}
else {
selector = selector.substr(1);
}
}
if (!selector.startsWith(")")) {
selectorIndex = parseSelector(data, selector, options, selectorIndex + 1);
if (selector.charAt(selectorIndex) !== ")") {
throw new Error("Missing closing parenthesis in :" + name_3 + " (" + selector + ")");
}
selector = selector.substr(1);
selectorIndex += 1;
}
else {
var pos = 1;
selectorIndex += 1;
var start = selectorIndex;
var counter = 1;
for (; counter > 0 && pos < selector.length; pos++) {
if (selector.charAt(pos) === "(" &&
!isEscaped(pos)) {
for (; counter > 0 && selectorIndex < selector.length; selectorIndex++) {
if (selector.charAt(selectorIndex) === "(" &&
!isEscaped(selectorIndex)) {
counter++;
}
else if (selector.charAt(pos) === ")" &&
!isEscaped(pos)) {
else if (selector.charAt(selectorIndex) === ")" &&
!isEscaped(selectorIndex)) {
counter--;

@@ -210,4 +235,3 @@ }

}
data = selector.substr(1, pos - 2);
selector = selector.substr(pos);
data = selector.slice(start, selectorIndex - 1);
if (stripQuotesFromPseudos.has(name_3)) {

@@ -224,16 +248,45 @@ var quot = data.charAt(0);

}
else if (reName.test(selector)) {
var name_4 = getName();
if ((_b = options.lowerCaseTags) !== null && _b !== void 0 ? _b : !options.xmlMode) {
name_4 = name_4.toLowerCase();
}
tokens.push({ type: "tag", name: name_4 });
}
else {
if (tokens.length &&
tokens[tokens.length - 1].type === "descendant") {
tokens.pop();
var namespace = null;
var name_4 = void 0;
if (firstChar === "*") {
selectorIndex += 1;
name_4 = "*";
}
addToken(subselects, tokens);
return selector;
else if (reName.test(selector.slice(selectorIndex))) {
name_4 = getName(0);
}
else {
/*
* We have finished parsing the selector.
* Remove descendant tokens at the end if they exist,
* and return the last index, so that parsing can be
* picked up from here.
*/
if (tokens.length &&
tokens[tokens.length - 1].type === "descendant") {
tokens.pop();
}
addToken(subselects, tokens);
return selectorIndex;
}
if (selector.charAt(selectorIndex) === "|") {
namespace = name_4;
if (selector.charAt(selectorIndex + 1) === "*") {
name_4 = "*";
selectorIndex += 2;
}
else {
name_4 = getName(1);
}
}
if (name_4 === "*") {
tokens.push({ type: "universal", namespace: namespace });
}
else {
if ((_b = options.lowerCaseTags) !== null && _b !== void 0 ? _b : !options.xmlMode) {
name_4 = name_4.toLowerCase();
}
tokens.push({ type: "tag", name: name_4, namespace: namespace });
}
}

@@ -243,3 +296,3 @@ }

addToken(subselects, tokens);
return selector;
return selectorIndex;
}

@@ -246,0 +299,0 @@ function addToken(subselects, tokens) {

import { Selector } from "./parse";
export default function stringify(token: Selector[][]): string;
/**
* Turns `selector` back into a string.
*
* @param selector Selector to stringify.
*/
export default function stringify(selector: Selector[][]): string;
//# sourceMappingURL=stringify.d.ts.map

@@ -27,5 +27,12 @@ "use strict";

"\\",
"(",
")",
]));
function stringify(token) {
return token.map(stringifySubselector).join(", ");
/**
* Turns `selector` back into a string.
*
* @param selector Selector to stringify.
*/
function stringify(selector) {
return selector.map(stringifySubselector).join(", ");
}

@@ -50,5 +57,5 @@ exports.default = stringify;

case "universal":
return "*";
return getNamespace(token.namespace) + "*";
case "tag":
return escapeName(token.name);
return getNamespacedName(token);
case "pseudo-element":

@@ -60,12 +67,10 @@ return "::" + escapeName(token.name);

if (typeof token.data === "string") {
return ":" + escapeName(token.name) + "(" + token.data + ")";
return ":" + escapeName(token.name) + "(" + escapeName(token.data) + ")";
}
return ":" + escapeName(token.name) + "(" + stringify(token.data) + ")";
case "attribute":
if (token.action === "exists") {
return "[" + escapeName(token.name) + "]";
}
case "attribute": {
if (token.name === "id" &&
token.action === "equals" &&
!token.ignoreCase) {
!token.ignoreCase &&
!token.namespace) {
return "#" + escapeName(token.value);

@@ -75,8 +80,22 @@ }

token.action === "element" &&
!token.ignoreCase) {
!token.ignoreCase &&
!token.namespace) {
return "." + escapeName(token.value);
}
return "[" + escapeName(token.name) + actionTypes[token.action] + "='" + escapeName(token.value) + "'" + (token.ignoreCase ? "i" : "") + "]";
var name_1 = getNamespacedName(token);
if (token.action === "exists") {
return "[" + name_1 + "]";
}
return "[" + name_1 + actionTypes[token.action] + "='" + escapeName(token.value) + "'" + (token.ignoreCase ? "i" : "") + "]";
}
}
}
function getNamespacedName(token) {
return "" + getNamespace(token.namespace) + escapeName(token.name);
}
function getNamespace(namespace) {
return namespace
? (namespace === "*" ? "*" : escapeName(namespace)) + "|"
: "";
}
function escapeName(str) {

@@ -83,0 +102,0 @@ return str

@@ -5,3 +5,3 @@ {

"description": "a CSS selector parser",
"version": "3.4.2",
"version": "4.0.0",
"funding": "https://github.com/sponsors/fb55",

@@ -8,0 +8,0 @@ "repository": {

@@ -28,7 +28,7 @@ # css-what [![Build Status](https://secure.travis-ci.org/fb55/css-what.svg?branch=master)](http://travis-ci.org/fb55/css-what)

**`CSSwhat.parse(str, options)` - Parses `str`, optionally with the passed `options`.**
**`CSSwhat.parse(selector, options)` - Parses `selector`, optionally with the passed `options`.**
The function returns a two-dimensional array. The first array represents selectors separated by commas (eg. `sub1, sub2`), the second contains the relevant tokens for that selector. Possible token types are:
| name | attributes | example | output |
| name | properties | example | output |
| ---------------- | --------------------------------------- | ------------- | ---------------------------------------------------------------------------------------- |

@@ -35,0 +35,0 @@ | `tag` | `name` | `div` | `{ type: 'tag', name: 'div' }` |

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc