Socket
Socket
Sign inDemoInstall

postcss-selector-parser

Package Overview
Dependencies
4
Maintainers
3
Versions
57
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.0 to 3.1.0

84

API.md

@@ -579,2 +579,26 @@ # API Documentation

### `attribute.qualifiedAttribute`
Returns the attribute name qualified with the namespace if one is given.
### `attribute.offsetOf(part)`
Returns the offset of the attribute part specified relative to the
start of the node of the output string. This is useful in raising
error messages about a specific part of the attribute, especially
in combination with `attribute.sourceIndex`.
Returns `-1` if the name is invalid or the value doesn't exist in this
attribute.
The legal values for `part` are:
* `"ns"` - alias for "namespace"
* `"namespace"` - the namespace if it exists.
* `"attribute"` - the attribute name
* `"attributeNS"` - the start of the attribute or its namespace
* `"operator"` - the match operator of the attribute
* `"value"` - The value (string or identifier)
* `"insensitive"` - the case insensitivity flag
### `attribute.raws.unquoted`

@@ -592,10 +616,58 @@

### `attribute.raws.insensitive`
### `attribute.spaces`
If there is an `i` specifying case insensitivity, returns that `i` along with the whitespace
around it.
Like `node.spaces` with the `before` and `after` values containing the spaces
around the element, the parts of the attribute can also have spaces before
and after them. The for each of `attribute`, `operator`, `value` and
`insensitive` there is corresponding property of the same nam in
`node.spaces` that has an optional `before` or `after` string containing only
whitespace.
```css
[id=Bar i ] /* " i " */
[id=Bar i ] /* " i " */
Note that corresponding values in `attributes.raws.spaces` contain values
including any comments. If set, these values will override the
`attribute.spaces` value. Take care to remove them if changing
`attribute.spaces`.
### `attribute.raws`
The raws object stores comments and other information necessary to re-render
the node exactly as it was in the source.
If a comment is embedded within the identifiers for the `namespace`, `attribute`
or `value` then a property is placed in the raws for that value containing the full source of the propery including comments.
If a comment is embedded within the space between parts of the attribute
then the raw for that space is set accordingly.
Setting an attribute's property `raws` value to be deleted.
For now, changing the spaces required also updating or removing any of the
raws values that override them.
Example: `[ /*before*/ href /* after-attr */ = /* after-operator */ te/*inside-value*/st/* wow */ /*omg*/i/*bbq*/ /*whodoesthis*/]` would parse as:
```js
{
attribute: "href",
operatator: "=",
value: "test",
spaces: {
before: '',
after: '',
attribute: { before: ' ', after: ' ' },
operator: { after: ' ' },
value: { after: ' ' },
insensitive: { after: ' ' }
},
raws: {
spaces: {
attribute: { before: ' /*before*/ ', after: ' /* after-attr */ ' },
operator: { after: ' /* after-operator */ ' },
value: { after: '/* wow */ /*omg*/' },
insensitive: { after: '/*bbq*/ /*whodoesthis*/' }
},
unquoted: 'test',
value: 'te/*inside-value*/st'
}
}
```

@@ -602,0 +674,0 @@

@@ -1,3 +0,11 @@

# 3.0.0-rc.0
# 3.1.0
* Fixed numerous bugs in attribute nodes relating to the handling of comments
and whitespace. There's significant changes to `attrNode.spaces` and `attrNode.raws` since the `3.0.0` release.
* Added `Attribute#offsetOf(part)` to get the offset location of
attribute parts like `"operator"` and `"value"`. This is most
often added to `Attribute#sourceIndex` for error reporting.
# 3.0.0
## Breaking changes

@@ -4,0 +12,0 @@

106

dist/parser.js

@@ -169,2 +169,3 @@ 'use strict';

var lastAdded = null;
var spaceAfterMeaningfulToken = false;

@@ -181,13 +182,17 @@ while (pos < len) {

}
spaceAfterMeaningfulToken = true;
if (this.options.lossy) {
break;
}
if (!lastAdded || this.content(next) === 'i') {
spaceBefore = content;
if (lastAdded) {
var spaceProp = 'spaces.' + lastAdded + '.after';
_dotProp2.default.set(node, spaceProp, _dotProp2.default.get(node, spaceProp, '') + content);
var commentProp = 'raws.spaces.' + lastAdded + '.after';
var existingComment = _dotProp2.default.get(node, commentProp);
if (existingComment) {
_dotProp2.default.set(node, commentProp, existingComment + content);
}
} else {
if (lastAdded === 'operator') {
_dotProp2.default.set(node, 'raws.' + lastAdded, _dotProp2.default.get(node, lastAdded) + content);
} else {
_dotProp2.default.set(node, lastAdded, _dotProp2.default.get(node, lastAdded) + content);
}
spaceBefore = spaceBefore + content;
commentBefore = commentBefore + content;
}

@@ -199,7 +204,19 @@ break;

lastAdded = 'operator';
} else if (!node.namespace && next) {
node.namespace = '' + this.parseSpace(spaceBefore) + content;
} else if ((!node.namespace || lastAdded === "namespace" && !spaceAfterMeaningfulToken) && next) {
if (spaceBefore) {
_dotProp2.default.set(node, 'spaces.attribute.before', spaceBefore);
spaceBefore = '';
}
if (commentBefore) {
_dotProp2.default.set(node, 'raws.spaces.attribute.before', spaceBefore);
commentBefore = '';
}
node.namespace = (node.namespace || "") + content;
var rawValue = _dotProp2.default.get(node, "raws.namespace");
if (rawValue) {
node.raws.namespace += content;
}
lastAdded = 'namespace';
spaceBefore = '';
}
spaceAfterMeaningfulToken = false;
break;

@@ -212,2 +229,3 @@ case tokens.dollar:

}
spaceAfterMeaningfulToken = false;
break;

@@ -220,2 +238,3 @@ case tokens.combinator:

if (content !== '|') {
spaceAfterMeaningfulToken = false;
break;

@@ -229,24 +248,53 @@ }

}
spaceAfterMeaningfulToken = false;
break;
case tokens.word:
if (next && this.content(next) === '|' && attr[pos + 2] && attr[pos + 2][0] !== tokens.equals && !node.operator && !node.namespace) {
if (next && this.content(next) === '|' && attr[pos + 2] && attr[pos + 2][0] !== tokens.equals && // this look-ahead probably fails with comment nodes involved.
!node.operator && !node.namespace) {
node.namespace = content;
lastAdded = 'namespace';
} else if (!node.attribute) {
node.attribute = '' + this.parseSpace(spaceBefore) + commentBefore + content;
} else if (!node.attribute || lastAdded === "attribute" && !spaceAfterMeaningfulToken) {
if (spaceBefore) {
_dotProp2.default.set(node, 'spaces.attribute.before', spaceBefore);
spaceBefore = '';
}
if (commentBefore) {
_dotProp2.default.set(node, 'raws.spaces.attribute.before', commentBefore);
commentBefore = '';
}
node.attribute = (node.attribute || "") + content;
var _rawValue = _dotProp2.default.get(node, "raws.attribute");
if (_rawValue) {
node.raws.attribute += content;
}
lastAdded = 'attribute';
spaceBefore = '';
commentBefore = '';
} else if (!node.value) {
node.value = content;
} else if (!node.value || lastAdded === "value" && !spaceAfterMeaningfulToken) {
node.value = (node.value || "") + content;
var _rawValue2 = _dotProp2.default.get(node, "raws.value");
if (_rawValue2) {
node.raws.value += content;
}
lastAdded = 'value';
_dotProp2.default.set(node, 'raws.unquoted', content);
_dotProp2.default.set(node, 'raws.unquoted', _dotProp2.default.get(node, 'raws.unquoted', '') + content);
} else if (content === 'i') {
node.insensitive = true;
if (!this.options.lossy) {
lastAdded = 'raws.insensitive';
_dotProp2.default.set(node, lastAdded, '' + spaceBefore + content);
spaceBefore = '';
if (node.value && (node.quoted || spaceAfterMeaningfulToken)) {
node.insensitive = true;
lastAdded = 'insensitive';
if (spaceBefore) {
_dotProp2.default.set(node, 'spaces.insensitive.before', spaceBefore);
spaceBefore = '';
}
if (commentBefore) {
_dotProp2.default.set(node, 'raws.spaces.insensitive.before', commentBefore);
commentBefore = '';
}
} else if (node.value) {
lastAdded = 'value';
node.value += 'i';
if (node.raws.value) {
node.raws.value += 'i';
}
}
}
spaceAfterMeaningfulToken = false;
break;

@@ -263,2 +311,3 @@ case tokens.str:

_dotProp2.default.set(node, 'raws.unquoted', content.slice(1, -1));
spaceAfterMeaningfulToken = false;
break;

@@ -274,8 +323,15 @@ case tokens.equals:

lastAdded = 'operator';
spaceAfterMeaningfulToken = false;
break;
case tokens.comment:
if (lastAdded) {
_dotProp2.default.set(node, lastAdded, _dotProp2.default.get(node, lastAdded) + content);
if (spaceAfterMeaningfulToken || next && next[0] === tokens.space) {
var lastComment = _dotProp2.default.get(node, 'raws.spaces.' + lastAdded + '.after', _dotProp2.default.get(node, 'spaces.' + lastAdded + '.after', ''));
_dotProp2.default.set(node, 'raws.spaces.' + lastAdded + '.after', lastComment + content);
} else {
var lastValue = _dotProp2.default.get(node, 'raws.' + lastAdded, _dotProp2.default.get(node, lastAdded, ''));
_dotProp2.default.set(node, 'raws.' + lastAdded, lastValue + content);
}
} else {
commentBefore = content;
commentBefore = commentBefore + content;
}

@@ -282,0 +338,0 @@ break;

@@ -5,2 +5,4 @@ '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 _namespace = require('./namespace');

@@ -31,26 +33,157 @@

_this.type = _types.ATTRIBUTE;
_this.raws = opts.raws || {};
_this.raws = _this.raws || {};
_this._constructed = true;
return _this;
}
Attribute.prototype.toString = function toString() {
var selector = [this.spaces.before, '[', this.ns, this.attribute];
Attribute.prototype._spacesFor = function _spacesFor(name) {
var attrSpaces = { before: '', after: '' };
var spaces = this.spaces[name] || {};
var rawSpaces = this.raws.spaces && this.raws.spaces[name] || {};
return Object.assign(attrSpaces, spaces, rawSpaces);
};
if (this.raws.operator) {
selector.push(this.raws.operator);
} else if (this.operator) {
selector.push(this.operator);
Attribute.prototype._valueFor = function _valueFor(name) {
return this.raws[name] || this[name];
};
Attribute.prototype._stringFor = function _stringFor(name) {
var spaceName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : name;
var concat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultAttrConcat;
var attrSpaces = this._spacesFor(spaceName);
return concat(this._valueFor(name), attrSpaces);
};
/**
* returns the offset of the attribute part specified relative to the
* start of the node of the output string.
*
* * "ns" - alias for "namespace"
* * "namespace" - the namespace if it exists.
* * "attribute" - the attribute name
* * "attributeNS" - the start of the attribute or its namespace
* * "operator" - the match operator of the attribute
* * "value" - The value (string or identifier)
* * "insensitive" - the case insensitivity flag;
* @param part One of the possible values inside an attribute.
* @returns -1 if the name is invalid or the value doesn't exist in this attribute.
*/
Attribute.prototype.offsetOf = function offsetOf(name) {
var count = 1;
var attributeSpaces = this._spacesFor("attribute");
count += attributeSpaces.before.length;
if (name === "namespace" || name === "ns") {
return this.namespace ? count : -1;
}
if (this.value) {
selector.push(this.value);
if (name === "attributeNS") {
return count;
}
if (this.raws.insensitive) {
selector.push(this.raws.insensitive);
} else if (this.insensitive) {
selector.push(' i');
count += this.namespaceString.length;
if (this.namespace) {
count += 1;
}
if (name === "attribute") {
return count;
}
count += this._valueFor("attribute").length;
count += attributeSpaces.after.length;
var operatorSpaces = this._spacesFor("operator");
count += operatorSpaces.before.length;
var operator = this._valueFor("operator");
if (name === "operator") {
return operator ? count : -1;
}
count += operator.length;
count += operatorSpaces.after.length;
var valueSpaces = this._spacesFor("value");
count += valueSpaces.before.length;
var value = this._valueFor("value");
if (name === "value") {
return value ? count : -1;
}
count += value.length;
count += valueSpaces.after.length;
var insensitiveSpaces = this._spacesFor("insensitive");
count += insensitiveSpaces.before.length;
if (name === "insensitive") {
return this.insensitive ? count : -1;
}
return -1;
};
Attribute.prototype.toString = function toString() {
var _this2 = this;
var selector = [this.spaces.before, '['];
selector.push(this._stringFor('qualifiedAttribute', 'attribute'));
if (this.operator && this.value) {
selector.push(this._stringFor('operator'));
selector.push(this._stringFor('value'));
selector.push(this._stringFor('insensitiveFlag', 'insensitive', function (attrValue, attrSpaces) {
if (attrValue.length > 0 && !_this2.quoted && attrSpaces.before.length === 0 && !(_this2.spaces.value && _this2.spaces.value.after)) {
attrSpaces.before = " ";
}
return defaultAttrConcat(attrValue, attrSpaces);
}));
}
selector.push(']');
return selector.concat(this.spaces.after).join('');
selector.push(this.spaces.after);
return selector.join('');
};
_createClass(Attribute, [{
key: 'qualifiedAttribute',
get: function get() {
return this.qualifiedName(this.raws.attribute || this.attribute);
}
}, {
key: 'insensitiveFlag',
get: function get() {
return this.insensitive ? 'i' : '';
}
}, {
key: 'value',
get: function get() {
return this._value;
},
set: function set(v) {
this._value = v;
if (this._constructed) {
delete this.raws.value;
}
}
}, {
key: 'namespace',
get: function get() {
return this._namespace;
},
set: function set(v) {
this._namespace = v;
if (this._constructed) {
delete this.raws.namespace;
}
}
}, {
key: 'attribute',
get: function get() {
return this._attribute;
},
set: function set(v) {
this._attribute = v;
if (this._constructed) {
delete this.raws.attibute;
}
}
}]);
return Attribute;

@@ -60,2 +193,7 @@ }(_namespace2.default);

exports.default = Attribute;
function defaultAttrConcat(attrValue, attrSpaces) {
return '' + attrSpaces.before + attrValue + attrSpaces.after;
}
module.exports = exports['default'];

@@ -28,12 +28,50 @@ 'use strict';

Namespace.prototype.qualifiedName = function qualifiedName(value) {
if (this.namespace) {
return this.namespaceString + '|' + value;
} else {
return value;
}
};
Namespace.prototype.toString = function toString() {
return [this.spaces.before, this.ns, String(this.value), this.spaces.after].join('');
return [this.spaces.before, this.qualifiedName(this.value), this.spaces.after].join('');
};
_createClass(Namespace, [{
key: 'namespace',
get: function get() {
return this._namespace;
},
set: function set(namespace) {
this._namespace = namespace;
if (this.raws) {
delete this.raws.namespace;
}
}
}, {
key: 'ns',
get: function get() {
var n = this.namespace;
return n ? (typeof n === 'string' ? n : '') + '|' : '';
return this._namespace;
},
set: function set(namespace) {
this._namespace = namespace;
if (this.raws) {
delete this.raws.namespace;
}
}
}, {
key: 'namespaceString',
get: function get() {
if (this.namespace) {
var ns = this.raws && this.raws.namespace || this.namespace;
if (ns === true) {
return '';
} else {
return ns;
}
} else {
return '';
}
}
}]);

@@ -40,0 +78,0 @@

@@ -45,13 +45,6 @@ 'use strict';

for (var key in opts) {
this[key] = opts[key];
}
var _opts$spaces = opts.spaces;
_opts$spaces = _opts$spaces === undefined ? {} : _opts$spaces;
var _opts$spaces$before = _opts$spaces.before,
before = _opts$spaces$before === undefined ? '' : _opts$spaces$before,
_opts$spaces$after = _opts$spaces.after,
after = _opts$spaces$after === undefined ? '' : _opts$spaces$after;
this.spaces = { before: before, after: after };
Object.assign(this, opts);
this.spaces = this.spaces || {};
this.spaces.before = this.spaces.before || '';
this.spaces.after = this.spaces.after || '';
}

@@ -58,0 +51,0 @@

{
"name": "postcss-selector-parser",
"version": "3.0.0",
"version": "3.1.0",
"devDependencies": {

@@ -5,0 +5,0 @@ "ava": "^0.20.0",

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc