You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.8 KiB
137 lines
3.8 KiB
var trim = require('./trim');
|
|
var each = require('./each');
|
|
var identity = require('./identity');
|
|
var map = require('./map');
|
|
|
|
var whitespace = '[\\x20\\t\\r\\n\\f]';
|
|
var identifier = '(?:\\\\[\\da-fA-F]{1,6}'.concat(
|
|
whitespace,
|
|
'?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+'
|
|
);
|
|
var attributes = '\\['
|
|
.concat(whitespace, '*(')
|
|
.concat(identifier, ')(?:')
|
|
.concat(whitespace, '*([*^$|!~]?=)')
|
|
.concat(
|
|
whitespace,
|
|
'*(?:\'((?:\\\\.|[^\\\\\'])*)\'|"((?:\\\\.|[^\\\\"])*)"|('
|
|
)
|
|
.concat(identifier, '))|)')
|
|
.concat(whitespace, '*\\]');
|
|
var pseudos = '::?('
|
|
.concat(
|
|
identifier,
|
|
')(?:\\(((\'((?:\\\\.|[^\\\\\'])*)\'|"((?:\\\\.|[^\\\\"])*)")|((?:\\\\.|[^\\\\()[\\]]|'
|
|
)
|
|
.concat(attributes, ')*)|.*)\\)|)');
|
|
var regComma = new RegExp('^'.concat(whitespace, '*,').concat(whitespace, '*'));
|
|
var regCombinators = new RegExp(
|
|
'^'
|
|
.concat(whitespace, '*([>+~]|')
|
|
.concat(whitespace, ')')
|
|
.concat(whitespace, '*')
|
|
);
|
|
var matchExpr = {
|
|
id: {
|
|
reg: new RegExp('^#('.concat(identifier, ')')),
|
|
value: function(raw) {
|
|
return raw.slice(1);
|
|
},
|
|
toStr: function(value) {
|
|
return '#'.concat(value);
|
|
}
|
|
},
|
|
class: {
|
|
reg: new RegExp('^\\.('.concat(identifier, ')')),
|
|
value: function(raw) {
|
|
return raw.slice(1);
|
|
},
|
|
toStr: function(value) {
|
|
return '.'.concat(value);
|
|
}
|
|
},
|
|
tag: {
|
|
reg: new RegExp('^('.concat(identifier, '|[*])')),
|
|
value: identity
|
|
},
|
|
attribute: {
|
|
reg: new RegExp('^'.concat(attributes)),
|
|
value: function(raw) {
|
|
return raw.slice(1, raw.length - 1);
|
|
},
|
|
toStr: function(value) {
|
|
return '['.concat(value, ']');
|
|
}
|
|
},
|
|
pseudo: {
|
|
reg: new RegExp('^'.concat(pseudos)),
|
|
value: identity
|
|
}
|
|
};
|
|
each(matchExpr, function(item) {
|
|
if (!item.value) item.value = identity;
|
|
if (!item.toStr) item.toStr = identity;
|
|
});
|
|
function parse(selector) {
|
|
selector = trim(selector);
|
|
var groups = [];
|
|
var tokens;
|
|
var match;
|
|
var matched;
|
|
while (selector) {
|
|
if (!matched || (match = regComma.exec(selector))) {
|
|
if (match) {
|
|
selector = selector.slice(match[0].length);
|
|
}
|
|
tokens = [];
|
|
groups.push(tokens);
|
|
}
|
|
matched = false;
|
|
if ((match = regCombinators.exec(selector))) {
|
|
matched = match.shift();
|
|
selector = selector.slice(matched.length);
|
|
matched = trim(matched);
|
|
if (!matched) matched = ' ';
|
|
tokens.push({
|
|
value: matched,
|
|
type: 'combinator'
|
|
});
|
|
}
|
|
each(matchExpr, function(_ref, type) {
|
|
var reg = _ref.reg,
|
|
value = _ref.value;
|
|
if ((match = reg.exec(selector))) {
|
|
matched = match.shift();
|
|
selector = selector.slice(matched.length);
|
|
matched = trim(matched);
|
|
tokens.push({
|
|
value: value(matched),
|
|
type: type
|
|
});
|
|
}
|
|
});
|
|
if (!matched) {
|
|
break;
|
|
}
|
|
}
|
|
return groups;
|
|
}
|
|
function stringify(groups) {
|
|
return map(groups, function(group) {
|
|
group = map(group, function(_ref2) {
|
|
var type = _ref2.type,
|
|
value = _ref2.value;
|
|
if (type === 'combinator') {
|
|
return value === ' ' ? value : ' '.concat(value, ' ');
|
|
}
|
|
return matchExpr[type].toStr(value);
|
|
});
|
|
return group.join('');
|
|
}).join(', ');
|
|
}
|
|
exports = {
|
|
parse: parse,
|
|
stringify: stringify
|
|
};
|
|
|
|
module.exports = exports;
|
|
|