optimizeComment(token, options);
break;
case Token.RULE:
- token[1] = tidyRules(token[1], !ie7Hack, adjacentSpace);
+ token[1] = tidyRules(token[1], !ie7Hack, adjacentSpace, context.warnings);
optimizeBody(token[2], context);
afterRules = true;
break;
token[2] = [];
} else if (lastToken[0] == Token.RULE && stringifyBody(token[2]) == stringifyBody(lastToken[2]) &&
!isSpecial(options, stringifyRules(token[1])) && !isSpecial(options, stringifyRules(lastToken[1]))) {
- lastToken[1] = tidyRules(lastToken[1].concat(token[1]), false, adjacentSpace);
+ lastToken[1] = tidyRules(lastToken[1].concat(token[1]), false, adjacentSpace, context.warnings);
token[2] = [];
} else {
lastToken = token;
var oldToken = candidates[candidateBody];
if (oldToken && !isSpecial(options, stringifyRules(token[1])) && !isSpecial(options, stringifyRules(oldToken[1]))) {
token[1] = token[2].length > 0 ?
- tidyRules(oldToken[1].concat(token[1]), false, adjacentSpace) :
+ tidyRules(oldToken[1].concat(token[1]), false, adjacentSpace, context.warnings) :
oldToken[1].concat(token[1]);
oldToken[2] = [];
var STAR_PLUS_HTML_HACK = '*+html ';
var STAR_FIRST_CHILD_PLUS_HTML_HACK = '*:first-child+html ';
+function hasInvalidCharacters(value) {
+ return value.indexOf(Marker.SINGLE_QUOTE) > -1 || value.indexOf(Marker.DOUBLE_QUOTE) > -1 ?
+ hasInvalidCharactersWithQuotes(value) :
+ hasInvalidCharactersWithoutQuotes(value);
+}
+
+function hasInvalidCharactersWithQuotes(value) {
+ var isEscaped;
+ var isInvalid = false;
+ var character;
+ var isQuote = false;
+ var i, l;
+
+ for (i = 0, l = value.length; i < l; i++) {
+ character = value[i];
+
+ if (isEscaped) {
+ // continue as always
+ } else if (character == Marker.SINGLE_QUOTE || character == Marker.DOUBLE_QUOTE) {
+ isQuote = !isQuote;
+ } else if (character == Marker.CLOSE_BRACE && !isQuote) {
+ isInvalid = true;
+ break;
+ }
+
+ isEscaped = character == Marker.BACK_SLASH;
+ }
+
+ return isInvalid;
+}
+
+function hasInvalidCharactersWithoutQuotes(value) {
+ return value.indexOf(Marker.CLOSE_BRACE) > -1;
+}
+
function removeWhitespace(value) {
var stripped = [];
var character;
return s1[0] > s2[0] ? 1 : -1;
}
-function tidyRules(rules, removeUnsupported, adjacentSpace) {
+function tidyRules(rules, removeUnsupported, adjacentSpace, warnings) {
var list = [];
var repeated = [];
var rule = rules[i];
var reduced = rule[0];
+ if (hasInvalidCharacters(reduced)) {
+ warnings.push('Invalid selector \'' + rule[0] + '\' at line ' + rule[1][0][0] + ', column ' + rule[1][0][1] + '. Ignoring.');
+ continue;
+ }
+
reduced = removeWhitespace(reduced);
reduced = removeQuotes(reduced);
level = levels.pop();
seekingValue = false;
- } else if (character == Marker.CLOSE_BRACE && level == Level.BLOCK && !isNested && position.index < source.length - 1) {
- // stray close brace at block level, e.g. @media screen {...}}<--
- externalContext.warnings.push('Extra \'}\' at line ' + position.line + ', column ' + position.column);
- // noop
+ } else if (character == Marker.CLOSE_BRACE && level == Level.BLOCK && !isNested && position.index <= source.length - 1) {
+ // stray close brace at block level, e.g. a{color:red}color:blue}<--
+ externalContext.warnings.push('Unexpected \'}\' at line ' + position.line + ', column ' + position.column + '.');
+ buffer.push(character);
} else if (character == Marker.CLOSE_BRACE && level == Level.BLOCK) {
// close brace at block level, e.g. @media screen {...}<--
break;
optimizerContext('invalid data tokenization', {
'extra top-level closing brace': [
'a{color:red}}p{width:auto}',
- 'a{color:red}p{width:auto}'
+ 'a{color:red}'
],
'extra top-level closing braces': [
'a{color:red}}}}p{width:auto}',
- 'a{color:red}p{width:auto}'
+ 'a{color:red}'
]
})
)
'rule',
[
[
- 'a',
+ '}a',
[
- [1, 16, undefined]
+ [1, 15, undefined]
]
]
],