* Fixed issue [#839](https://github.com/jakubpawlowicz/clean-css/issues/839) - allows URIs in import inlining rules.
* Fixed issue [#840](https://github.com/jakubpawlowicz/clean-css/issues/840) - allows input source map as map object.
* Fixed issue [#843](https://github.com/jakubpawlowicz/clean-css/issues/843) - regression in selector handling.
+* Fixed issue [#847](https://github.com/jakubpawlowicz/clean-css/issues/847) - regression in handling invalid selectors.
[3.4.23 / 2016-12-17](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.22...v3.4.23)
==================
var RELATION_PATTERN = /[>\+~]/;
var WHITESPACE_PATTERN = /\s/;
+var LESS_THAN = '<';
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;
// continue as always
} else if (character == Marker.SINGLE_QUOTE || character == Marker.DOUBLE_QUOTE) {
isQuote = !isQuote;
- } else if (character == Marker.CLOSE_BRACE && !isQuote) {
+ } else if (!isQuote && (character == Marker.CLOSE_BRACE || character == Marker.EXCLAMATION || character == LESS_THAN)) {
+ isInvalid = true;
+ break;
+ } else if (!isQuote && i === 0 && RELATION_PATTERN.test(character)) {
isInvalid = true;
break;
}
return isInvalid;
}
-function hasInvalidCharactersWithoutQuotes(value) {
- return value.indexOf(Marker.CLOSE_BRACE) > -1;
-}
-
function removeWhitespace(value, beautify) {
var stripped = [];
var character;
if (seekingValue && buffer.length > 0) {
serializedBuffer = buffer.join('').replace(TAIL_BROKEN_VALUE_PATTERN, '');
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
+
+ buffer = [];
+ }
+
+ if (buffer.length > 0) {
+ externalContext.warnings.push('Invalid character(s) \'' + buffer.join('') + '\' at ' + formatPosition(metadata) + '. Ignoring.');
}
return allTokens;
assert.isEmpty(minified.errors);
},
'should raise one warning': function (error, minified) {
- assert.lengthOf(minified.warnings, 1);
+ assert.lengthOf(minified.warnings, 2);
assert.equal(minified.warnings[0], 'Unexpected \'}\' at 1:16.');
+ assert.equal(minified.warnings[1], 'Invalid character(s) \'}\' at 1:16. Ignoring.');
}
},
'warnings on unexpected body': {
'no rule scope': [
'{overflow:hidden}',
''
+ ],
+ 'invalid characters #1': [
+ '<![CDATA[p.b{background:red}]]>',
+ ''
+ ],
+ 'invalid characters #2': [
+ '<funky{background:red}',
+ ''
+ ],
+ 'invalid characters #3 - relation at the beginning': [
+ '>.funky{background:red}',
+ ''
]
}, { advanced: false })
)
'logs them correctly': function (warnings) {
assert.deepEqual(warnings, ['Missing \'}\' at one.css:1:15.']);
}
+ },
+ 'warnings - extra characters': {
+ 'topic': function () {
+ var warnings = [];
+
+ tokenize('<![CDATA[p.b{background:red}]]>', {
+ inputSourceMapTracker: inputSourceMapTracker(),
+ options: {},
+ source: 'one.css',
+ warnings: warnings
+ });
+
+ return warnings;
+ },
+ 'logs them correctly': function (warnings) {
+ assert.deepEqual(warnings, ['Invalid character(s) \']]>\' at one.css:1:28. Ignoring.']);
+ }
}
})
.addBatch({