[2.2.0 / 2014-xx-xx (UNRELEASED)](https://github.com/GoalSmashers/clean-css/compare/v2.1.4...HEAD)
==================
+* Adds a better algorithm for quotation marks' removal.
* Adds a better non-adjacent optimizer compatible with the upcoming new property optimizer.
* Moves quotation matching into a QuoteScanner class.
* Fixed issue [#247](https://github.com/GoalSmashers/clean-css/issues/247) - removes deprecated `selectorsMergeMode` switch.
var ExpressionsProcessor = require('./text/expressions');
var FreeTextProcessor = require('./text/free');
var UrlsProcessor = require('./text/urls');
+var NameQuotesProcessor = require('./text/name-quotes');
var SelectorsOptimizer = require('./selectors/optimizer');
var expressionsProcessor = new ExpressionsProcessor();
var freeTextProcessor = new FreeTextProcessor();
var urlsProcessor = new UrlsProcessor();
+ var nameQuotesProcessor = new NameQuotesProcessor();
if (options.debug) {
this.startedAt = process.hrtime();
});
// strip parentheses in animation & font names
- replace(/(animation|animation\-name|font|font\-family):([^;}]+)/g, function(match, propertyName, def) {
- if (def.indexOf('\'{') === 0)
- return match;
-
- return propertyName + ':' + def.replace(/['"]([a-zA-Z][a-zA-Z\d\-_]+)['"]/g, '$1');
+ replace(function removeQuotes() {
+ data = nameQuotesProcessor.process(data);
});
// strip parentheses in @keyframes
--- /dev/null
+(function() {
+ var OPEN_BRACE = '{';
+ var SEMICOLON = ';';
+ var COLON = ':';
+
+ var PropertyScanner = function PropertyScanner(data) {
+ this.data = data;
+ };
+
+ PropertyScanner.prototype.nextAt = function(cursor) {
+ var lastColon = this.data.lastIndexOf(COLON, cursor);
+ var lastOpenBrace = this.data.lastIndexOf(OPEN_BRACE, cursor);
+ var lastSemicolon = this.data.lastIndexOf(SEMICOLON, cursor);
+ var startAt = Math.max(lastOpenBrace, lastSemicolon);
+
+ return this.data.substring(startAt + 1, lastColon).trim();
+ };
+
+ module.exports = PropertyScanner;
+})();
--- /dev/null
+(function() {
+ var QuoteScanner = require('./quote-scanner');
+ var PropertyScanner = require('../properties/scanner');
+
+ var NameQuotes = function NameQuotes() {};
+
+ var STRIPPABLE = /['"][a-zA-Z][a-zA-Z\d\-_]+['"]/;
+
+ var properties = [
+ 'animation',
+ '-moz-animation',
+ '-o-animation',
+ '-webkit-animation',
+ 'animation-name',
+ '-moz-animation-name',
+ '-o-animation-name',
+ '-webkit-animation-name',
+ 'font',
+ 'font-family'
+ ];
+
+ NameQuotes.prototype.process = function(data) {
+ var scanner = new PropertyScanner(data);
+
+ return new QuoteScanner(data).each(function(match, store, cursor) {
+ var lastProperty = scanner.nextAt(cursor);
+ if (properties.indexOf(lastProperty) > -1) {
+ if (STRIPPABLE.test(match))
+ match = match.substring(1, match.length - 1);
+ }
+
+ store.push(match);
+ });
+ };
+
+ module.exports = NameQuotes;
+})();
var text = data.substring(nextStart, nextEnd + 1);
tempData.push(data.substring(cursor, nextStart));
- callback(text, tempData);
+ callback(text, tempData, nextStart);
cursor = nextEnd + 1;
}
'a{background:url("/very/long/\
path")}',
'a{background:url(/very/long/path)}'
- ],
- 'do not remove quotation from enclosed JSON (weird, I know)': "p{font-family:'{ \"current\" : \"large\", \"all\" : [\"small\", \"medium\", \"large\"], \"position\" : 2 }'}"
+ ]
}),
'urls rewriting - no root or target': cssContext({
'no @import': 'a{background:url(test/data/partials/extra/down.gif) 0 0 no-repeat}',