for (i=0, len=part.modifiers.length; i < len; i++) {
modifier = part.modifiers[i];
if (Pseudos.isElement(modifier.text)) {
for (j=0, num=modifier.args.length; j < num; j++) {
updateValues(modifier.args[j]);
for (i=0, len=selector.parts.length; i < len; i++) {
part = selector.parts[i];
if (part instanceof SelectorPart) {
return new Specificity(0, b, c, d);
},{"./Pseudos":12,"./SelectorPart":14}],17:[function(require,module,exports){
module.exports = TokenStream;
var TokenStreamBase = require("../util/TokenStreamBase");
var PropertyValuePart = require("./PropertyValuePart");
var Tokens = require("./Tokens");
nonascii = /^[\u00A0-\uFFFF]$/,
whitespace = /\u0009|\u000a|\u000c|\u000d|\u0020/;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
return c !== null && h.test(c);
return c !== null && /\d/.test(c);
function isWhitespace(c) {
return c !== null && whitespace.test(c);
return c !== null && nl.test(c);
function isNameStart(c) {
return c !== null && /[a-z_\u00A0-\uFFFF\\]/i.test(c);
return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c));
function isIdentStart(c) {
return c !== null && (isNameStart(c) || /\-\\/.test(c));
function mix(receiver, supplier) {
for (var prop in supplier) {
if (Object.prototype.hasOwnProperty.call(supplier, prop)) {
receiver[prop] = supplier[prop];
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
* A token stream that produces CSS tokens.
* @param {String|Reader} input The source of text to tokenize.
* @namespace parserlib.css
function TokenStream(input) {
TokenStreamBase.call(this, input, Tokens);
TokenStream.prototype = mix(new TokenStreamBase(), {
* Overrides the TokenStreamBase method of the same name
* @return {Object} A token object representing the next token.
startLine = reader.getLine(),
startCol = reader.getCol();
if (reader.peek() === "*") {
token = this.commentToken(c, startLine, startCol);
token = this.charToken(c, startLine, startCol);
if (reader.peek() === "=") {
token = this.comparisonToken(c, startLine, startCol);
token = this.charToken(c, startLine, startCol);
token = this.stringToken(c, startLine, startCol);
if (isNameChar(reader.peek())) {
token = this.hashToken(c, startLine, startCol);
token = this.charToken(c, startLine, startCol);
if (isDigit(reader.peek())) {
token = this.numberToken(c, startLine, startCol);
token = this.charToken(c, startLine, startCol);
if (reader.peek() === "-") { //could be closing HTML-style comment
token = this.htmlCommentEndToken(c, startLine, startCol);
} else if (isNameStart(reader.peek())) {
token = this.identOrFunctionToken(c, startLine, startCol);
token = this.charToken(c, startLine, startCol);
token = this.importantToken(c, startLine, startCol);
token = this.atRuleToken(c, startLine, startCol);
token = this.notToken(c, startLine, startCol);
token = this.htmlCommentStartToken(c, startLine, startCol);
if (/[^\r\n\f]/.test(reader.peek())) {
token = this.identOrFunctionToken(this.readEscape(c, true), startLine, startCol);
token = this.charToken(c, startLine, startCol);
if (reader.peek() === "+") {
token = this.unicodeRangeToken(c, startLine, startCol);
token = this.numberToken(c, startLine, startCol);
token = this.whitespaceToken(c, startLine, startCol);
token = this.identOrFunctionToken(c, startLine, startCol);
token = this.charToken(c, startLine, startCol);
//make sure this token is wanted
if (!token && c === null) {
token = this.createToken(Tokens.EOF, null, startLine, startCol);
//-------------------------------------------------------------------------
// Methods to create tokens
//-------------------------------------------------------------------------
* Produces a token based on available data and the current
* reader position information. This method is called by other
* private methods to create tokens and is never called directly.
* @param {int} tt The token type.
* @param {String} value The text value of the token.
* @param {int} startLine The beginning line for the character.
* @param {int} startCol The beginning column for the character.
* @param {Object} options (Optional) Specifies a channel property
* to indicate that a different channel should be scanned
* and/or a hide property indicating that the token should
* @return {Object} A token object.
createToken: function(tt, value, startLine, startCol, options) {
var reader = this._reader;
channel: options.channel,
endChar: options.endChar,
hide: options.hide || false,
endLine: reader.getLine(),
//-------------------------------------------------------------------------
// Methods to create specific tokens
//-------------------------------------------------------------------------
* Produces a token for any at-rule. If the at-rule is unknown, then
* the token is for a single "@" character.
* @param {String} first The first character for the token.
* @param {int} startLine The beginning line for the character.
* @param {int} startCol The beginning column for the character.
* @return {Object} A token object.
atRuleToken: function(first, startLine, startCol) {
* First, mark where we are. There are only four @ rules,
* so anything else is really just an invalid token.
* Basically, if this doesn't match one of the known @
* rules, just return '@' as an unknown token and allow
* parsing to continue after that point.
//try to find the at-keyword
tt = Tokens.type(rule.toLowerCase());
//if it's not valid, use the first character only and reset the reader
if (tt === Tokens.CHAR || tt === Tokens.UNKNOWN) {
return this.createToken(tt, rule, startLine, startCol);
* Produces a character token based on the given character
* and location in the stream. If there's a special (non-standard)
* token name, this is used; otherwise CHAR is used.
* @param {String} c The character for the token.
* @param {int} startLine The beginning line for the character.
* @param {int} startCol The beginning column for the character.
* @return {Object} A token object.
charToken: function(c, startLine, startCol) {
opts.endChar = Tokens[tt].endChar;
return this.createToken(tt, c, startLine, startCol, opts);
* Produces a character token based on the given character
* and location in the stream. If there's a special (non-standard)
* token name, this is used; otherwise CHAR is used.
* @param {String} first The first character for the token.
* @param {int} startLine The beginning line for the character.
* @param {int} startCol The beginning column for the character.
* @return {Object} A token object.
commentToken: function(first, startLine, startCol) {
var comment = this.readComment(first);
return this.createToken(Tokens.COMMENT, comment, startLine, startCol);
* Produces a comparison token based on the given character
* and location in the stream. The next character must be
* read and is already known to be an equals sign.
* @param {String} c The character for the token.
* @param {int} startLine The beginning line for the character.
* @param {int} startCol The beginning column for the character.
* @return {Object} A token object.
* @method comparisonToken
comparisonToken: function(c, startLine, startCol) {
var reader = this._reader,
comparison = c + reader.read(),
tt = Tokens.type(comparison) || Tokens.CHAR;
return this.createToken(tt, comparison, startLine, startCol);
* Produces a hash token based on the specified information. The
* first character provided is the pound sign (#) and then this
* method reads a name afterward.
* @param {String} first The first character (#) in the hash name.
* @param {int} startLine The beginning line for the character.
* @param {int} startCol The beginning column for the character.
* @return {Object} A token object.
hashToken: function(first, startLine, startCol) {
var name = this.readName(first);
return this.createToken(Tokens.HASH, name, startLine, startCol);
* Produces a CDO or CHAR token based on the specified information. The