Socket
Socket
Sign inDemoInstall

postcss-selector-parser

Package Overview
Dependencies
Maintainers
1
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

postcss-selector-parser - npm Package Compare versions

Comparing version 2.2.3 to 3.0.0-rc.0

dist/tokenTypes.js

57

API.md

@@ -11,3 +11,3 @@ # API Documentation

```js
var parser = require('postcss-selector-parser');
const parser = require('postcss-selector-parser');
```

@@ -20,7 +20,7 @@

```js
var processor = parser();
const processor = parser();
// or, with optional transform function
var transform = function (selectors) {
selectors.eachUniversal(function (selector) {
const transform = selectors => {
selectors.eachUniversal(selector => {
selector.remove();

@@ -30,6 +30,6 @@ });

var processor = parser(transform)
const processor = parser(transform)
// Example
var result = processor.process('*.class').result;
const result = processor.processSync('*.class');
// => .class

@@ -228,3 +228,3 @@ ```

```js
var id = parser.id({value: 'search'});
const id = parser.id({value: 'search'});
console.log(String(id));

@@ -239,3 +239,3 @@ // => #search

```js
var next = id.next();
const next = id.next();
if (next && next.type !== 'combinator') {

@@ -251,4 +251,4 @@ throw new Error('Qualified IDs are not allowed!');

```js
var attr = selectors.first.first;
var className = parser.className({value: 'test'});
const attr = selectors.first.first;
const className = parser.className({value: 'test'});
attr.replaceWith(className);

@@ -277,3 +277,3 @@ ```

```js
var cloned = parser.id({value: 'search'});
const cloned = parser.id({value: 'search'});
String(cloned);

@@ -418,4 +418,4 @@

```js
var className;
selectors.each(function (selector, index) {
let className;
selectors.each((selector, index) => {
if (selector.type === 'class') {

@@ -442,3 +442,3 @@ className = selector.value;

```js
selectors.walk(function (selector, index) {
selectors.walk((selector, index) => {
// all nodes

@@ -480,3 +480,3 @@ });

// (input) => h1 h2>>h3
var list = selectors.first.split((selector) => {
const list = selectors.first.split(selector => {
return selector.type === 'combinator';

@@ -499,3 +499,3 @@ });

```js
var id = parser.id({value: 'search'});
const id = parser.id({value: 'search'});
selector.append(id);

@@ -513,5 +513,5 @@ ```

```js
selectors.walk(function (selector) {
selectors.walk(selector => {
if (selector.type !== 'class') {
var className = parser.className({value: 'theme-name'});
const className = parser.className({value: 'theme-name'});
selector.parent.insertAfter(selector, className);

@@ -614,15 +614,24 @@ }

### `process(cssText, [options])`
### `process|processSync(css, [options])`
Processes the `cssText`, returning the parsed output
Processes the `css`, returning the parsed output. An async method is exposed
as `process`.
```js
var processor = parser();
const processor = parser();
var result = processor.process(' .class').result;
const result = processor.processSync(' .class');
// => .class
// Asynchronous operation
processor.process(' .class').then(result => /* ... */);
// To have the parser normalize whitespace values, utilize the options
var result = processor.process(' .class ', {lossless: false}).result;
const result = processor.processSync(' .class ', {lossless: false});
// => .class
// For better syntax errors, pass a PostCSS Rule node.
const postcss = require('postcss');
const rule = postcss.rule({selector: 'a'});
const result = process.process(rule);
```

@@ -632,3 +641,3 @@

* `cssText (string)`: The css to be parsed.
* `css (string|object)`: Either a selector string or a PostCSS Rule node.
* `[options] (object)`: Process options

@@ -635,0 +644,0 @@

@@ -0,1 +1,22 @@

# 3.0.0-rc.0
## Breaking changes
* Some tweaks to the tokenizer/attribute selector parsing mean that whitespace
locations might be slightly different to the 2.x code.
* Better attribute selector parsing with more validation; postcss-selector-parser
no longer uses regular expressions to parse attribute selectors.
* Added an async API (thanks to @jacobp100); the default `process` API is now
async, and the sync API is now accessed through `processSync` instead.
* Tweaks handling of Less interpolation (thanks to @jwilsson).
* Removes support for Node 0.12.
## Other changes
* Set the parent when inserting a node (thanks to @chriseppstein).
* Correctly adjust indices when using insertBefore/insertAfter (thanks to @tivac).
* Fixes handling of namespaces with qualified tag selectors.
* Now accepts a PostCSS rule node for better syntax errors.
* Now more memory efficient when tokenizing selectors.
# 2.2.3

@@ -2,0 +23,0 @@

@@ -7,5 +7,5 @@ 'use strict';

var _flatten = require('flatten');
var _dotProp = require('dot-prop');
var _flatten2 = _interopRequireDefault(_flatten);
var _dotProp2 = _interopRequireDefault(_dotProp);

@@ -76,2 +76,6 @@ var _indexesOf = require('indexes-of');

var _tokenTypes = require('./tokenTypes');
var tokens = _interopRequireWildcard(_tokenTypes);
var _types = require('./selectors/types');

@@ -87,2 +91,15 @@

function getSource(startLine, startColumn, endLine, endColumn) {
return {
start: {
line: startLine,
column: startColumn
},
end: {
line: endLine,
column: endColumn
}
};
}
var Parser = function () {

@@ -97,10 +114,13 @@ function Parser(input) {

var selectors = new _selector2.default();
this.root.append(selectors);
var selector = new _selector2.default();
this.root.append(selector);
this.current = selector;
this.current = selectors;
this.css = typeof input.css === 'string' ? input.css : input.css.selector;
if (this.lossy) {
this.tokens = (0, _tokenize2.default)({ safe: input.safe, css: input.css.trim() });
this.css = this.css.trim();
this.tokens = (0, _tokenize2.default)({ safe: input.safe, css: this.css });
} else {
this.tokens = (0, _tokenize2.default)(input);
this.tokens = (0, _tokenize2.default)(Object.assign({}, input, { css: this.css }));
}

@@ -112,55 +132,136 @@

Parser.prototype.attribute = function attribute() {
var str = '';
var attr = void 0;
var attr = [];
var startingToken = this.currToken;
this.position++;
while (this.position < this.tokens.length && this.currToken[0] !== ']') {
str += this.tokens[this.position][1];
while (this.position < this.tokens.length && this.currToken[0] !== tokens.closeSquare) {
attr.push(this.currToken);
this.position++;
}
if (this.position === this.tokens.length && !~str.indexOf(']')) {
this.error('Expected a closing square bracket.');
if (this.currToken[0] !== tokens.closeSquare) {
return this.expected('closing square bracket', this.currToken[5]);
}
var parts = str.split(/((?:[*~^$|]?=))([^]*)/);
var namespace = parts[0].split(/(\|)/g);
var attributeProps = {
operator: parts[1],
value: parts[2],
source: {
start: {
line: startingToken[2],
column: startingToken[3]
},
end: {
line: this.currToken[2],
column: this.currToken[3]
}
},
sourceIndex: startingToken[4]
var len = attr.length;
var node = {
source: getSource(startingToken[1], startingToken[2], this.currToken[3], this.currToken[4]),
sourceIndex: startingToken[5]
};
if (namespace.length > 1) {
if (namespace[0] === '') {
namespace[0] = true;
}
attributeProps.attribute = this.parseValue(namespace[2]);
attributeProps.namespace = this.parseNamespace(namespace[0]);
} else {
attributeProps.attribute = this.parseValue(parts[0]);
if (len === 1 && !~[tokens.word].indexOf(attr[0][0])) {
return this.expected('attribute', attr[0][5]);
}
attr = new _attribute2.default(attributeProps);
if (parts[2]) {
var insensitive = parts[2].split(/(\s+i\s*?)$/);
var trimmedValue = insensitive[0].trim();
attr.value = this.lossy ? trimmedValue : insensitive[0];
if (insensitive[1]) {
attr.insensitive = true;
if (!this.lossy) {
attr.raws.insensitive = insensitive[1];
}
var pos = 0;
var spaceBefore = '';
var commentBefore = '';
var lastAdded = null;
while (pos < len) {
var token = attr[pos];
var content = this.content(token);
var next = attr[pos + 1];
switch (token[0]) {
case tokens.space:
if (len === 1 || pos === 0 && this.content(next) === '|') {
return this.expected('attribute', token[5], content);
}
if (this.lossy) {
break;
}
if (!lastAdded || this.content(next) === 'i') {
spaceBefore = content;
} else {
_dotProp2.default.set(node, lastAdded, _dotProp2.default.get(node, lastAdded) + content);
}
break;
case tokens.asterisk:
if (next[0] === tokens.equals) {
node.operator = content;
lastAdded = 'operator';
} else if (!node.namespace && next) {
node.namespace = '' + this.parseSpace(spaceBefore) + content;
lastAdded = 'namespace';
spaceBefore = '';
}
break;
case tokens.dollar:
case tokens.caret:
if (next[0] === tokens.equals) {
node.operator = content;
lastAdded = 'operator';
}
break;
case tokens.combinator:
if (content === '~' && next[0] === tokens.equals) {
node.operator = content;
lastAdded = 'operator';
}
if (content !== '|') {
break;
}
if (next[0] === tokens.equals) {
node.operator = content;
lastAdded = 'operator';
} else if (!node.namespace && !node.attribute) {
node.namespace = true;
}
break;
case tokens.word:
if (next && this.content(next) === '|' && attr[pos + 2] && attr[pos + 2][0] !== tokens.equals && !node.operator && !node.namespace) {
node.namespace = content;
lastAdded = 'namespace';
} else if (!node.attribute) {
node.attribute = '' + this.parseSpace(spaceBefore) + commentBefore + content;
lastAdded = 'attribute';
spaceBefore = '';
commentBefore = '';
} else if (!node.value) {
node.value = content;
lastAdded = 'value';
_dotProp2.default.set(node, 'raws.unquoted', content);
} else if (content === 'i') {
node.insensitive = true;
if (!this.lossy) {
lastAdded = 'raws.insensitive';
_dotProp2.default.set(node, lastAdded, '' + spaceBefore + content);
spaceBefore = '';
}
}
break;
case tokens.str:
if (!node.attribute || !node.operator) {
return this.error('Expected an attribute followed by an operator preceding the string.', {
index: token[5]
});
}
node.value = content;
node.quoted = true;
lastAdded = 'value';
_dotProp2.default.set(node, 'raws.unquoted', content.slice(1, -1));
break;
case tokens.equals:
if (!node.attribute) {
return this.expected('attribute', token[5], content);
}
if (node.value) {
return this.error('Unexpected "=" found; an operator was already defined.', { index: token[5] });
}
node.operator = node.operator ? '' + node.operator + content : content;
lastAdded = 'operator';
break;
case tokens.comment:
if (lastAdded) {
_dotProp2.default.set(node, lastAdded, _dotProp2.default.get(node, lastAdded) + content);
} else {
commentBefore = content;
}
break;
default:
return this.error('Unexpected "' + content + '" found.', { index: token[5] });
}
attr.quoted = trimmedValue[0] === '\'' || trimmedValue[0] === '"';
attr.raws.unquoted = attr.quoted ? trimmedValue.slice(1, -1) : trimmedValue;
pos++;
}
this.newNode(attr);
this.newNode(new _attribute2.default(node));
this.position++;

@@ -170,3 +271,4 @@ };

Parser.prototype.combinator = function combinator() {
if (this.currToken[1] === '|') {
var current = this.currToken;
if (this.content() === '|') {
return this.namespace();

@@ -176,28 +278,17 @@ }

value: '',
source: {
start: {
line: this.currToken[2],
column: this.currToken[3]
},
end: {
line: this.currToken[2],
column: this.currToken[3]
}
},
sourceIndex: this.currToken[4]
source: getSource(current[1], current[2], current[3], current[4]),
sourceIndex: current[5]
});
while (this.position < this.tokens.length && this.currToken && (this.currToken[0] === 'space' || this.currToken[0] === 'combinator')) {
if (this.nextToken && this.nextToken[0] === 'combinator') {
node.spaces.before = this.parseSpace(this.currToken[1]);
node.source.start.line = this.nextToken[2];
node.source.start.column = this.nextToken[3];
node.source.end.column = this.nextToken[3];
node.source.end.line = this.nextToken[2];
node.sourceIndex = this.nextToken[4];
} else if (this.prevToken && this.prevToken[0] === 'combinator') {
node.spaces.after = this.parseSpace(this.currToken[1]);
} else if (this.currToken[0] === 'combinator') {
node.value = this.currToken[1];
} else if (this.currToken[0] === 'space') {
node.value = this.parseSpace(this.currToken[1], ' ');
while (this.position < this.tokens.length && this.currToken && (this.currToken[0] === tokens.space || this.currToken[0] === tokens.combinator)) {
var content = this.content();
if (this.nextToken && this.nextToken[0] === tokens.combinator) {
node.spaces.before = this.parseSpace(content);
node.source = getSource(this.nextToken[1], this.nextToken[2], this.nextToken[3], this.nextToken[4]);
node.sourceIndex = this.nextToken[5];
} else if (this.prevToken && this.prevToken[0] === tokens.combinator) {
node.spaces.after = this.parseSpace(content);
} else if (this.currToken[0] === tokens.combinator) {
node.value = content;
} else if (this.currToken[0] === tokens.space) {
node.value = this.parseSpace(content, ' ');
}

@@ -215,5 +306,5 @@ this.position++;

}
var selectors = new _selector2.default();
this.current.parent.append(selectors);
this.current = selectors;
var selector = new _selector2.default();
this.current.parent.append(selector);
this.current = selector;
this.position++;

@@ -223,42 +314,35 @@ };

Parser.prototype.comment = function comment() {
var node = new _comment2.default({
value: this.currToken[1],
source: {
start: {
line: this.currToken[2],
column: this.currToken[3]
},
end: {
line: this.currToken[4],
column: this.currToken[5]
}
},
sourceIndex: this.currToken[6]
});
this.newNode(node);
var current = this.currToken;
this.newNode(new _comment2.default({
value: this.content(),
source: getSource(current[1], current[2], current[3], current[4]),
sourceIndex: current[5]
}));
this.position++;
};
Parser.prototype.error = function error(message) {
throw new this.input.error(message); // eslint-disable-line new-cap
Parser.prototype.error = function error(message, opts) {
throw new this.input.error(message, opts); // eslint-disable-line new-cap
};
Parser.prototype.missingBackslash = function missingBackslash() {
return this.error('Expected a backslash preceding the semicolon.');
return this.error('Expected a backslash preceding the semicolon.', {
index: this.currToken[5]
});
};
Parser.prototype.missingParenthesis = function missingParenthesis() {
return this.error('Expected opening parenthesis.');
return this.expected('opening parenthesis', this.currToken[5]);
};
Parser.prototype.missingSquareBracket = function missingSquareBracket() {
return this.error('Expected opening square bracket.');
return this.expected('opening square bracket', this.currToken[5]);
};
Parser.prototype.namespace = function namespace() {
var before = this.prevToken && this.prevToken[1] || true;
if (this.nextToken[0] === 'word') {
var before = this.prevToken && this.content(this.prevToken) || true;
if (this.nextToken[0] === tokens.word) {
this.position++;
return this.word(before);
} else if (this.nextToken[0] === '*') {
} else if (this.nextToken[0] === tokens.asterisk) {
this.position++;

@@ -270,15 +354,7 @@ return this.universal(before);

Parser.prototype.nesting = function nesting() {
var current = this.currToken;
this.newNode(new _nesting2.default({
value: this.currToken[1],
source: {
start: {
line: this.currToken[2],
column: this.currToken[3]
},
end: {
line: this.currToken[2],
column: this.currToken[3]
}
},
sourceIndex: this.currToken[4]
value: this.content(),
source: getSource(current[1], current[2], current[3], current[4]),
sourceIndex: current[5]
}));

@@ -290,2 +366,4 @@ this.position++;

var last = this.current.last;
var balanced = 1;
this.position++;
if (last && last.type === types.PSEUDO) {

@@ -296,9 +374,7 @@ var selector = new _selector2.default();

this.current = selector;
var balanced = 1;
this.position++;
while (this.position < this.tokens.length && balanced) {
if (this.currToken[0] === '(') {
if (this.currToken[0] === tokens.openParenthesis) {
balanced++;
}
if (this.currToken[0] === ')') {
if (this.currToken[0] === tokens.closeParenthesis) {
balanced--;

@@ -309,21 +385,16 @@ }

} else {
selector.parent.source.end.line = this.currToken[2];
selector.parent.source.end.column = this.currToken[3];
selector.parent.source.end.line = this.currToken[3];
selector.parent.source.end.column = this.currToken[4];
this.position++;
}
}
if (balanced) {
this.error('Expected closing parenthesis.');
}
this.current = cache;
} else {
var _balanced = 1;
this.position++;
last.value += '(';
while (this.position < this.tokens.length && _balanced) {
if (this.currToken[0] === '(') {
_balanced++;
while (this.position < this.tokens.length && balanced) {
if (this.currToken[0] === tokens.openParenthesis) {
balanced++;
}
if (this.currToken[0] === ')') {
_balanced--;
if (this.currToken[0] === tokens.closeParenthesis) {
balanced--;
}

@@ -333,6 +404,6 @@ last.value += this.parseParenthesisToken(this.currToken);

}
if (_balanced) {
this.error('Expected closing parenthesis.');
}
}
if (balanced) {
return this.expected('closing parenthesis', this.currToken[5]);
}
};

@@ -345,34 +416,25 @@

var startingToken = this.currToken;
while (this.currToken && this.currToken[0] === ':') {
pseudoStr += this.currToken[1];
while (this.currToken && this.currToken[0] === tokens.colon) {
pseudoStr += this.content();
this.position++;
}
if (!this.currToken) {
return this.error('Expected pseudo-class or pseudo-element');
return this.expected(['pseudo-class', 'pseudo-element'], this.position - 1);
}
if (this.currToken[0] === 'word') {
var pseudo = void 0;
if (this.currToken[0] === tokens.word) {
this.splitWord(false, function (first, length) {
pseudoStr += first;
pseudo = new _pseudo2.default({
_this.newNode(new _pseudo2.default({
value: pseudoStr,
source: {
start: {
line: startingToken[2],
column: startingToken[3]
},
end: {
line: _this.currToken[4],
column: _this.currToken[5]
}
},
sourceIndex: startingToken[4]
});
_this.newNode(pseudo);
if (length > 1 && _this.nextToken && _this.nextToken[0] === '(') {
_this.error('Misplaced parenthesis.');
source: getSource(startingToken[1], startingToken[2], _this.currToken[3], _this.currToken[4]),
sourceIndex: startingToken[5]
}));
if (length > 1 && _this.nextToken && _this.nextToken[0] === tokens.openParenthesis) {
_this.error('Misplaced parenthesis.', {
index: _this.nextToken[5]
});
}
});
} else {
this.error('Unexpected "' + this.currToken[0] + '" found.');
return this.expected(['pseudo-class', 'pseudo-element'], this.currToken[5]);
}

@@ -382,9 +444,9 @@ };

Parser.prototype.space = function space() {
var token = this.currToken;
var content = this.content();
// Handle space before and after the selector
if (this.position === 0 || this.prevToken[0] === ',' || this.prevToken[0] === '(') {
this.spaces = this.parseSpace(token[1]);
if (this.position === 0 || this.prevToken[0] === tokens.comma || this.prevToken[0] === tokens.openParenthesis) {
this.spaces = this.parseSpace(content);
this.position++;
} else if (this.position === this.tokens.length - 1 || this.nextToken[0] === ',' || this.nextToken[0] === ')') {
this.current.last.spaces.after = this.parseSpace(token[1]);
} else if (this.position === this.tokens.length - 1 || this.nextToken[0] === tokens.comma || this.nextToken[0] === tokens.closeParenthesis) {
this.current.last.spaces.after = this.parseSpace(content);
this.position++;

@@ -397,16 +459,7 @@ } else {

Parser.prototype.string = function string() {
var token = this.currToken;
var current = this.currToken;
this.newNode(new _string2.default({
value: this.currToken[1],
source: {
start: {
line: token[2],
column: token[3]
},
end: {
line: token[4],
column: token[5]
}
},
sourceIndex: token[6]
value: this.content(),
source: getSource(current[1], current[2], current[3], current[4]),
sourceIndex: current[5]
}));

@@ -418,19 +471,11 @@ this.position++;

var nextToken = this.nextToken;
if (nextToken && nextToken[1] === '|') {
if (nextToken && this.content(nextToken) === '|') {
this.position++;
return this.namespace();
}
var current = this.currToken;
this.newNode(new _universal2.default({
value: this.currToken[1],
source: {
start: {
line: this.currToken[2],
column: this.currToken[3]
},
end: {
line: this.currToken[2],
column: this.currToken[3]
}
},
sourceIndex: this.currToken[4]
value: this.content(),
source: getSource(current[1], current[2], current[3], current[4]),
sourceIndex: current[5]
}), namespace);

@@ -444,11 +489,11 @@ this.position++;

var nextToken = this.nextToken;
var word = this.currToken[1];
while (nextToken && nextToken[0] === 'word') {
var word = this.content();
while (nextToken && ~[tokens.dollar, tokens.caret, tokens.equals, tokens.word].indexOf(nextToken[0])) {
this.position++;
var current = this.currToken[1];
var current = this.content();
word += current;
if (current.lastIndexOf('\\') === current.length - 1) {
var next = this.nextToken;
if (next && next[0] === 'space') {
word += this.parseSpace(next[1], ' ');
if (next && next[0] === tokens.space) {
word += this.parseSpace(this.content(next), ' ');
this.position++;

@@ -468,3 +513,3 @@ }

}
var indices = (0, _sortAscending2.default)((0, _uniq2.default)((0, _flatten2.default)([[0], hasClass, hasId])));
var indices = (0, _sortAscending2.default)((0, _uniq2.default)([0].concat(hasClass, hasId)));
indices.forEach(function (ind, i) {

@@ -477,16 +522,10 @@ var index = indices[i + 1] || word.length;

var node = void 0;
var current = _this2.currToken;
var sourceIndex = current[5] + indices[i];
var source = getSource(current[1], current[2] + ind, current[3], current[2] + (index - 1));
if (~hasClass.indexOf(ind)) {
node = new _className2.default({
value: value.slice(1),
source: {
start: {
line: _this2.currToken[2],
column: _this2.currToken[3] + ind
},
end: {
line: _this2.currToken[4],
column: _this2.currToken[3] + (index - 1)
}
},
sourceIndex: _this2.currToken[6] + indices[i]
source: source,
sourceIndex: sourceIndex
});

@@ -496,13 +535,4 @@ } else if (~hasId.indexOf(ind)) {

value: value.slice(1),
source: {
start: {
line: _this2.currToken[2],
column: _this2.currToken[3] + ind
},
end: {
line: _this2.currToken[4],
column: _this2.currToken[3] + (index - 1)
}
},
sourceIndex: _this2.currToken[6] + indices[i]
source: source,
sourceIndex: sourceIndex
});

@@ -512,16 +542,9 @@ } else {

value: value,
source: {
start: {
line: _this2.currToken[2],
column: _this2.currToken[3] + ind
},
end: {
line: _this2.currToken[4],
column: _this2.currToken[3] + (index - 1)
}
},
sourceIndex: _this2.currToken[6] + indices[i]
source: source,
sourceIndex: sourceIndex
});
}
_this2.newNode(node, namespace);
// Ensure that the namespace is used only once
namespace = null;
});

@@ -533,3 +556,3 @@ this.position++;

var nextToken = this.nextToken;
if (nextToken && nextToken[1] === '|') {
if (nextToken && this.content(nextToken) === '|') {
this.position++;

@@ -550,12 +573,12 @@ return this.namespace();

switch (this.currToken[0]) {
case 'space':
case tokens.space:
this.space();
break;
case 'comment':
case tokens.comment:
this.comment();
break;
case '(':
case tokens.openParenthesis:
this.parentheses();
break;
case ')':
case tokens.closeParenthesis:
if (throwOnParenthesis) {

@@ -565,33 +588,34 @@ this.missingParenthesis();

break;
case '[':
case tokens.openSquare:
this.attribute();
break;
case ']':
this.missingSquareBracket();
break;
case 'at-word':
case 'word':
case tokens.dollar:
case tokens.caret:
case tokens.equals:
case tokens.word:
this.word();
break;
case ':':
case tokens.colon:
this.pseudo();
break;
case ';':
this.missingBackslash();
break;
case ',':
case tokens.comma:
this.comma();
break;
case '*':
case tokens.asterisk:
this.universal();
break;
case '&':
case tokens.ampersand:
this.nesting();
break;
case 'combinator':
case tokens.combinator:
this.combinator();
break;
case 'string':
case tokens.str:
this.string();
break;
// These cases throw; no break needed.
case tokens.closeSquare:
this.missingSquareBracket();
case tokens.semicolon:
this.missingBackslash();
}

@@ -604,2 +628,14 @@ };

Parser.prototype.expected = function expected(description, index, found) {
if (Array.isArray(description)) {
var last = description.pop();
description = description.join(', ') + ' or ' + last;
}
var an = /^[aeiou]/.test(description[0]) ? 'an' : 'a';
if (!found) {
return this.error('Expected ' + an + ' ' + description + '.', { index: index });
}
return this.error('Expected ' + an + ' ' + description + ', found "' + found + '" instead.', { index: index });
};
Parser.prototype.parseNamespace = function parseNamespace(namespace) {

@@ -618,20 +654,26 @@ if (this.lossy && typeof namespace === 'string') {

Parser.prototype.parseSpace = function parseSpace(space, replacement) {
return this.lossy ? replacement || '' : space;
Parser.prototype.parseSpace = function parseSpace(space) {
var replacement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
return this.lossy ? replacement : space;
};
Parser.prototype.parseValue = function parseValue(value) {
return this.lossy && value && typeof value === 'string' ? value.trim() : value;
if (!this.lossy || !value || typeof value !== 'string') {
return value;
}
return value.trim();
};
Parser.prototype.parseParenthesisToken = function parseParenthesisToken(token) {
var content = this.content(token);
if (!this.lossy) {
return token[1];
return content;
}
if (token[0] === 'space') {
return this.parseSpace(token[1], ' ');
if (token[0] === tokens.space) {
return this.parseSpace(content, ' ');
}
return this.parseValue(token[1]);
return this.parseValue(content);
};

@@ -650,2 +692,8 @@

Parser.prototype.content = function content() {
var token = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.currToken;
return this.css.slice(token[5], token[6]);
};
_createClass(Parser, [{

@@ -652,0 +700,0 @@ key: 'currToken',

@@ -5,4 +5,2 @@ 'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _parser = require('./parser');

@@ -21,27 +19,41 @@

this.func = func || function noop() {};
this.funcRes = null;
return this;
}
Processor.prototype.process = function process(selectors) {
Processor.prototype._input = function _input(rule) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var input = new _parser2.default({
css: selectors,
error: function error(e) {
throw new Error(e);
return new _parser2.default({
css: rule,
error: function error(e, opts) {
if (typeof rule === 'string') {
throw new Error(e);
}
throw rule.error(e, opts); // eslint-disable-line new-cap
},
options: options
});
this.res = input;
this.func(input);
return this;
};
_createClass(Processor, [{
key: 'result',
get: function get() {
return String(this.res);
Processor.prototype.process = function process(rule, options) {
var input = void 0;
try {
input = this._input(rule, options);
} catch (e) {
return Promise.reject(e);
}
}]);
return Promise.resolve(this.func(input)).then(function () {
return String(input);
});
};
Processor.prototype.processSync = function processSync(rule) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var input = this._input(rule, options);
this.func(input);
return String(input);
};
return Processor;

@@ -48,0 +60,0 @@ }();

@@ -22,3 +22,5 @@ 'use strict';

function Attribute(opts) {
function Attribute() {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, Attribute);

@@ -29,3 +31,3 @@

_this.type = _types.ATTRIBUTE;
_this.raws = {};
_this.raws = opts.raws || {};
return _this;

@@ -32,0 +34,0 @@ }

@@ -104,5 +104,8 @@ 'use strict';

Container.prototype.insertAfter = function insertAfter(oldNode, newNode) {
newNode.parent = this;
var oldIndex = this.index(oldNode);
this.nodes.splice(oldIndex + 1, 0, newNode);
newNode.parent = this;
var index = void 0;

@@ -112,3 +115,3 @@ for (var id in this.indexes) {

if (oldIndex <= index) {
this.indexes[id] = index + this.nodes.length;
this.indexes[id] = index + 1;
}

@@ -121,10 +124,13 @@ }

Container.prototype.insertBefore = function insertBefore(oldNode, newNode) {
newNode.parent = this;
var oldIndex = this.index(oldNode);
this.nodes.splice(oldIndex, 0, newNode);
newNode.parent = this;
var index = void 0;
for (var id in this.indexes) {
index = this.indexes[id];
if (oldIndex <= index) {
this.indexes[id] = index + this.nodes.length;
if (index <= oldIndex) {
this.indexes[id] = index + 1;
}

@@ -131,0 +137,0 @@ }

@@ -5,63 +5,50 @@ 'use strict';

exports.default = tokenize;
var singleQuote = 39,
doubleQuote = 34,
backslash = 92,
slash = 47,
newline = 10,
space = 32,
feed = 12,
tab = 9,
cr = 13,
plus = 43,
gt = 62,
tilde = 126,
pipe = 124,
comma = 44,
openBracket = 40,
closeBracket = 41,
openSq = 91,
closeSq = 93,
semicolon = 59,
asterisk = 42,
colon = 58,
ampersand = 38,
at = 64,
atEnd = /[ \n\t\r\{\(\)'"\\;/]/g,
wordEnd = /[ \n\t\r\(\)\*:;@!&'"\+\|~>,\[\]\\]|\/(?=\*)/g;
var _tokenTypes = require('./tokenTypes');
var t = _interopRequireWildcard(_tokenTypes);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
var wordEnd = /[ \n\t\r\(\)\*:;!&'"\+\|~>,=$^\[\]\\]|\/(?=\*)/g;
function tokenize(input) {
var tokens = [];
var css = input.css.valueOf();
var _css = css,
length = _css.length;
var offset = -1;
var line = 1;
var start = 0;
var end = 0;
var code = void 0,
content = void 0,
endColumn = void 0,
endLine = void 0,
escaped = void 0,
escapePos = void 0,
last = void 0,
lines = void 0,
next = void 0,
quote = void 0,
lines = void 0,
last = void 0,
content = void 0,
escape = void 0,
nextLine = void 0,
nextOffset = void 0,
escaped = void 0,
escapePos = void 0;
quote = void 0,
tokenType = void 0;
var length = css.length;
var offset = -1;
var line = 1;
var pos = 0;
var unclosed = function unclosed(what, end) {
function unclosed(what, fix) {
if (input.safe) {
css += end;
css += fix;
next = css.length - 1;
} else {
throw input.error('Unclosed ' + what, line, pos - offset, pos);
throw input.error('Unclosed ' + what, line, start - offset, start);
}
};
}
while (pos < length) {
code = css.charCodeAt(pos);
while (start < length) {
code = css.charCodeAt(start);
if (code === newline) {
offset = pos;
if (code === t.newline) {
offset = start;
line += 1;

@@ -71,74 +58,63 @@ }

switch (code) {
case newline:
case space:
case tab:
case cr:
case feed:
next = pos;
case t.newline:
case t.space:
case t.tab:
case t.cr:
case t.feed:
next = start;
do {
next += 1;
code = css.charCodeAt(next);
if (code === newline) {
if (code === t.newline) {
offset = next;
line += 1;
}
} while (code === space || code === newline || code === tab || code === cr || code === feed);
} while (code === t.space || code === t.newline || code === t.tab || code === t.cr || code === t.feed);
tokens.push(['space', css.slice(pos, next), line, pos - offset, pos]);
pos = next - 1;
tokenType = t.space;
endLine = line;
endColumn = start - offset;
end = next;
break;
case plus:
case gt:
case tilde:
case pipe:
next = pos;
case t.plus:
case t.greaterThan:
case t.tilde:
case t.pipe:
next = start;
do {
next += 1;
code = css.charCodeAt(next);
} while (code === plus || code === gt || code === tilde || code === pipe);
tokens.push(['combinator', css.slice(pos, next), line, pos - offset, pos]);
pos = next - 1;
break;
} while (code === t.plus || code === t.greaterThan || code === t.tilde || code === t.pipe);
case asterisk:
tokens.push(['*', '*', line, pos - offset, pos]);
tokenType = t.combinator;
endLine = line;
endColumn = start - offset;
end = next;
break;
case ampersand:
tokens.push(['&', '&', line, pos - offset, pos]);
// Consume these characters as single tokens.
case t.asterisk:
case t.ampersand:
case t.comma:
case t.equals:
case t.dollar:
case t.caret:
case t.openSquare:
case t.closeSquare:
case t.colon:
case t.semicolon:
case t.openParenthesis:
case t.closeParenthesis:
next = start;
tokenType = code;
endLine = line;
endColumn = start - offset;
end = next + 1;
break;
case comma:
tokens.push([',', ',', line, pos - offset, pos]);
break;
case openSq:
tokens.push(['[', '[', line, pos - offset, pos]);
break;
case closeSq:
tokens.push([']', ']', line, pos - offset, pos]);
break;
case colon:
tokens.push([':', ':', line, pos - offset, pos]);
break;
case semicolon:
tokens.push([';', ';', line, pos - offset, pos]);
break;
case openBracket:
tokens.push(['(', '(', line, pos - offset, pos]);
break;
case closeBracket:
tokens.push([')', ')', line, pos - offset, pos]);
break;
case singleQuote:
case doubleQuote:
quote = code === singleQuote ? "'" : '"';
next = pos;
case t.singleQuote:
case t.doubleQuote:
quote = code === t.singleQuote ? "'" : '"';
next = start;
do {

@@ -151,3 +127,3 @@ escaped = false;

escapePos = next;
while (css.charCodeAt(escapePos - 1) === backslash) {
while (css.charCodeAt(escapePos - 1) === t.backslash) {
escapePos -= 1;

@@ -158,36 +134,29 @@ escaped = !escaped;

tokens.push(['string', css.slice(pos, next + 1), line, pos - offset, line, next - offset, pos]);
pos = next;
tokenType = t.str;
endLine = line;
endColumn = start - offset;
end = next + 1;
break;
case at:
atEnd.lastIndex = pos + 1;
atEnd.test(css);
if (atEnd.lastIndex === 0) {
next = css.length - 1;
} else {
next = atEnd.lastIndex - 2;
}
tokens.push(['at-word', css.slice(pos, next + 1), line, pos - offset, line, next - offset, pos]);
pos = next;
break;
case backslash:
next = pos;
escape = true;
while (css.charCodeAt(next + 1) === backslash) {
case t.backslash:
next = start;
escaped = true;
while (css.charCodeAt(next + 1) === t.backslash) {
next += 1;
escape = !escape;
escaped = !escaped;
}
code = css.charCodeAt(next + 1);
if (escape && code !== slash && code !== space && code !== newline && code !== tab && code !== cr && code !== feed) {
if (escaped && code !== t.slash && code !== t.space && code !== t.newline && code !== t.tab && code !== t.cr && code !== t.feed) {
next += 1;
}
tokens.push(['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset, pos]);
pos = next;
tokenType = t.word;
endLine = line;
endColumn = next - offset;
end = next + 1;
break;
default:
if (code === slash && css.charCodeAt(pos + 1) === asterisk) {
next = css.indexOf('*/', pos + 2) + 1;
if (code === t.slash && css.charCodeAt(start + 1) === t.asterisk) {
next = css.indexOf('*/', start + 2) + 1;
if (next === 0) {

@@ -197,3 +166,3 @@ unclosed('comment', '*/');

content = css.slice(pos, next + 1);
content = css.slice(start, next + 1);
lines = content.split('\n');

@@ -210,9 +179,8 @@ last = lines.length - 1;

tokens.push(['comment', content, line, pos - offset, nextLine, next - nextOffset, pos]);
offset = nextOffset;
tokenType = t.comment;
line = nextLine;
pos = next;
endLine = nextLine;
endColumn = next - nextOffset;
} else {
wordEnd.lastIndex = pos + 1;
wordEnd.lastIndex = start + 1;
wordEnd.test(css);

@@ -225,10 +193,28 @@ if (wordEnd.lastIndex === 0) {

tokens.push(['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset, pos]);
pos = next;
tokenType = t.word;
endLine = line;
endColumn = next - offset;
}
end = next + 1;
break;
}
pos++;
// Ensure that the token structure remains consistent
tokens.push([tokenType, // [0] Token type
line, // [1] Starting line
start - offset, // [2] Starting column
endLine, // [3] Ending line
endColumn, // [4] Ending column
start, // [5] Start position / Source index
end] // [6] End position
);
// Reset offset for the next token
if (nextOffset) {
offset = nextOffset;
nextOffset = null;
}
start = end;
}

@@ -235,0 +221,0 @@

{
"name": "postcss-selector-parser",
"version": "2.2.3",
"version": "3.0.0-rc.0",
"devDependencies": {
"ava": "^0.17.0",
"ava": "^0.20.0",
"babel-cli": "^6.4.0",

@@ -22,3 +22,4 @@ "babel-core": "^6.4.0",

"minimist": "^1.2.0",
"nyc": "^10.0.0"
"nyc": "^10.0.0",
"postcss": "^6.0.6"
},

@@ -36,7 +37,6 @@ "main": "dist/index.js",

"report": "nyc report --reporter=html",
"test": "nyc ava src/__tests__/*.js",
"test-012": "nyc ava src/__tests__/*.js"
"test": "nyc ava src/__tests__/*.js"
},
"dependencies": {
"flatten": "^1.0.2",
"dot-prop": "^4.1.1",
"indexes-of": "^1.0.1",

@@ -46,2 +46,5 @@ "uniq": "^1.0.1"

"license": "MIT",
"engines": {
"node": ">=4"
},
"homepage": "https://github.com/postcss/postcss-selector-parser",

@@ -48,0 +51,0 @@ "author": {

@@ -16,5 +16,5 @@ # postcss-selector-parser [![Build Status](https://travis-ci.org/postcss/postcss-selector-parser.svg?branch=master)](https://travis-ci.org/postcss/postcss-selector-parser)

```js
var parser = require('postcss-selector-parser');
var transform = function (selectors) {
selectors.eachInside(function (selector) {
const parser = require('postcss-selector-parser');
const transform = selectors => {
selectors.eachInside(selector => {
// do something with the selector

@@ -25,3 +25,3 @@ console.log(String(selector))

var transformed = parser(transform).process('h1, h2, h3').result;
const transformed = parser(transform).processSync('h1, h2, h3');
```

@@ -32,7 +32,10 @@

```js
var parser = require('postcss-selector-parser');
var normalized = parser().process('h1, h2, h3', {lossless:false}).result;
const parser = require('postcss-selector-parser');
const normalized = parser().processSync('h1, h2, h3', {lossless: false});
// -> h1,h2,h3
```
Async support is provided through `parser.process` and will resolve a Promise
with the resulting selector string.
## API

@@ -39,0 +42,0 @@

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