From 7fa31a2cdfd27705e47e800ef53fa3780a1b7948 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Sat, 1 Mar 2014 04:46:18 +0000 Subject: [PATCH] Moves quotation matching into a QuoteScanner class. --- History.md | 1 + lib/text/free.js | 90 +++++++++------------------------------ lib/text/quote-scanner.js | 70 ++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 70 deletions(-) create mode 100644 lib/text/quote-scanner.js diff --git a/History.md b/History.md index 245ba2c5..83281c26 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ ================== * 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. [2.1.4 / 2014-03-01](https://github.com/GoalSmashers/clean-css/compare/v2.1.3...v2.1.4) diff --git a/lib/text/free.js b/lib/text/free.js index ea303686..97f24e5b 100644 --- a/lib/text/free.js +++ b/lib/text/free.js @@ -1,76 +1,26 @@ -var EscapeStore = require('./escape-store'); +(function() { + var EscapeStore = require('./escape-store'); + var QuoteScanner = require('./quote-scanner'); -module.exports = function Free() { - var texts = new EscapeStore('FREE_TEXT'); - - var findNonEscapedEnd = function(data, matched, start) { - var end = start; - while (true) { - end = data.indexOf(matched, end); - - if (end > -1 && data[end - 1] == '\\') { - end += 1; - continue; - } else { - break; - } - } - - return end; + var Free = function Free() { + this.matches = new EscapeStore('FREE_TEXT'); }; - return { - // Strip content tags by replacing them by the a special - // marker for further restoring. It's done via string scanning - // instead of regexps to speed up the process. - escape: function(data) { - var tempData = []; - var nextStart = 0; - var nextEnd = 0; - var cursor = 0; - var matchedParenthesis = null; - var singleParenthesis = '\''; - var doubleParenthesis = '"'; - var dataLength = data.length; - - for (; nextEnd < data.length;) { - var nextStartSingle = data.indexOf(singleParenthesis, nextEnd + 1); - var nextStartDouble = data.indexOf(doubleParenthesis, nextEnd + 1); - - if (nextStartSingle == -1) - nextStartSingle = dataLength; - if (nextStartDouble == -1) - nextStartDouble = dataLength; - - if (nextStartSingle < nextStartDouble) { - nextStart = nextStartSingle; - matchedParenthesis = singleParenthesis; - } else { - nextStart = nextStartDouble; - matchedParenthesis = doubleParenthesis; - } + // Strip content tags by replacing them by the a special + // marker for further restoring. It's done via string scanning + // instead of regexps to speed up the process. + Free.prototype.escape = function(data) { + var self = this; - if (nextStart == -1) - break; - - nextEnd = findNonEscapedEnd(data, matchedParenthesis, nextStart + 1); - if (nextEnd == -1) - break; - - var text = data.substring(nextStart, nextEnd + 1); - var placeholder = texts.store(text); - tempData.push(data.substring(cursor, nextStart)); - tempData.push(placeholder); - cursor = nextEnd + 1; - } - - return tempData.length > 0 ? - tempData.join('') + data.substring(cursor, data.length) : - data; - }, + return new QuoteScanner(data).each(function(match, store) { + var placeholder = self.matches.store(match); + store.push(placeholder); + }); + }; - restore: function(data) { - return data.replace(texts.placeholderRegExp, texts.restore); - } + Free.prototype.restore = function(data) { + return data.replace(this.matches.placeholderRegExp, this.matches.restore); }; -}; + + module.exports = Free; +})(); diff --git a/lib/text/quote-scanner.js b/lib/text/quote-scanner.js new file mode 100644 index 00000000..4bab694c --- /dev/null +++ b/lib/text/quote-scanner.js @@ -0,0 +1,70 @@ +(function() { + var QuoteScanner = function QuoteScanner(data) { + this.data = data; + }; + + var findNonEscapedEnd = function(data, matched, start) { + var end = start; + while (true) { + end = data.indexOf(matched, end); + + if (end > -1 && data[end - 1] == '\\') { + end += 1; + continue; + } else { + break; + } + } + + return end; + }; + + QuoteScanner.prototype.each = function(callback) { + var data = this.data; + var tempData = []; + var nextStart = 0; + var nextEnd = 0; + var cursor = 0; + var matchedMark = null; + var singleMark = '\''; + var doubleMark = '"'; + var dataLength = data.length; + + for (; nextEnd < data.length;) { + var nextStartSingle = data.indexOf(singleMark, nextEnd + 1); + var nextStartDouble = data.indexOf(doubleMark, nextEnd + 1); + + if (nextStartSingle == -1) + nextStartSingle = dataLength; + if (nextStartDouble == -1) + nextStartDouble = dataLength; + + if (nextStartSingle < nextStartDouble) { + nextStart = nextStartSingle; + matchedMark = singleMark; + } else { + nextStart = nextStartDouble; + matchedMark = doubleMark; + } + + if (nextStart == -1) + break; + + nextEnd = findNonEscapedEnd(data, matchedMark, nextStart + 1); + if (nextEnd == -1) + break; + + var text = data.substring(nextStart, nextEnd + 1); + tempData.push(data.substring(cursor, nextStart)); + callback(text, tempData); + + cursor = nextEnd + 1; + } + + return tempData.length > 0 ? + tempData.join('') + data.substring(cursor, data.length) : + data; + }; + + module.exports = QuoteScanner; +})(); -- 2.34.1