Improves QuoteScanner.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Thu, 25 Sep 2014 12:21:42 +0000 (13:21 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Fri, 10 Oct 2014 20:22:44 +0000 (21:22 +0100)
* Removes module wrapper.
* Adds set of tests.

lib/text/quote-scanner.js
test/text/quote-scanner-test.js [new file with mode: 0644]

index f04e26b..8981dac 100644 (file)
@@ -1,91 +1,89 @@
-(function() {
-  var QuoteScanner = function QuoteScanner(data) {
-    this.data = data;
-  };
-
-  var findQuoteEnd = function(data, matched, cursor, oldCursor) {
-    var commentStartMark = '/*';
-    var commentEndMark = '*/';
-    var escapeMark = '\\';
-    var blockEndMark = '}';
-    var dataPrefix = data.substring(oldCursor, cursor);
-    var commentEndedAt = dataPrefix.lastIndexOf(commentEndMark, cursor);
-    var commentStartedAt = dataPrefix.lastIndexOf(commentStartMark, cursor);
-    var commentStarted = false;
-
-    if (commentEndedAt >= cursor && commentStartedAt > -1)
-      commentStarted = true;
-    if (commentStartedAt < cursor && commentStartedAt > commentEndedAt)
-      commentStarted = true;
-
-    if (commentStarted) {
-      var commentEndsAt = data.indexOf(commentEndMark, cursor);
-      if (commentEndsAt > -1)
-        return commentEndsAt;
-
-      commentEndsAt = data.indexOf(blockEndMark, cursor);
-      return commentEndsAt > -1 ? commentEndsAt - 1 : data.length;
+var QuoteScanner = function QuoteScanner(data) {
+  this.data = data;
+};
+
+var findQuoteEnd = function (data, matched, cursor, oldCursor) {
+  var commentStartMark = '/*';
+  var commentEndMark = '*/';
+  var escapeMark = '\\';
+  var blockEndMark = '}';
+  var dataPrefix = data.substring(oldCursor, cursor);
+  var commentEndedAt = dataPrefix.lastIndexOf(commentEndMark, cursor);
+  var commentStartedAt = dataPrefix.lastIndexOf(commentStartMark, cursor);
+  var commentStarted = false;
+
+  if (commentEndedAt >= cursor && commentStartedAt > -1)
+    commentStarted = true;
+  if (commentStartedAt < cursor && commentStartedAt > commentEndedAt)
+    commentStarted = true;
+
+  if (commentStarted) {
+    var commentEndsAt = data.indexOf(commentEndMark, cursor);
+    if (commentEndsAt > -1)
+      return commentEndsAt;
+
+    commentEndsAt = data.indexOf(blockEndMark, cursor);
+    return commentEndsAt > -1 ? commentEndsAt - 1 : data.length;
+  }
+
+  while (true) {
+    if (data[cursor] === undefined)
+      break;
+    if (data[cursor] == matched && (data[cursor - 1] != escapeMark || data[cursor - 2] == escapeMark))
+      break;
+
+    cursor++;
+  }
+
+  return cursor;
+};
+
+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;
     }
 
-    while (true) {
-      if (data[cursor] === undefined)
-        break;
-      if (data[cursor] == matched && (data[cursor - 1] != escapeMark || data[cursor - 2] == escapeMark))
-        break;
+    if (nextStart == -1)
+      break;
 
-      cursor++;
-    }
+    nextEnd = findQuoteEnd(data, matchedMark, nextStart + 1, cursor);
+    if (nextEnd == -1)
+      break;
 
-    return cursor;
-  };
-
-  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 = findQuoteEnd(data, matchedMark, nextStart + 1, cursor);
-      if (nextEnd == -1)
-        break;
-
-      var text = data.substring(nextStart, nextEnd + 1);
-      tempData.push(data.substring(cursor, nextStart));
-      if (text.length > 0)
-        callback(text, tempData, nextStart);
-
-      cursor = nextEnd + 1;
-    }
+    var text = data.substring(nextStart, nextEnd + 1);
+    tempData.push(data.substring(cursor, nextStart));
+    if (text.length > 0)
+      callback(text, tempData, nextStart);
+
+    cursor = nextEnd + 1;
+  }
 
-    return tempData.length > 0 ?
-      tempData.join('') + data.substring(cursor, data.length) :
-      data;
-  };
+  return tempData.length > 0 ?
+    tempData.join('') + data.substring(cursor, data.length) :
+    data;
+};
 
-  module.exports = QuoteScanner;
-})();
+module.exports = QuoteScanner;
diff --git a/test/text/quote-scanner-test.js b/test/text/quote-scanner-test.js
new file mode 100644 (file)
index 0000000..9b89f65
--- /dev/null
@@ -0,0 +1,98 @@
+var vows = require('vows');
+var assert = require('assert');
+var QuoteScanner = require('../../lib/text/quote-scanner');
+
+vows.describe(QuoteScanner)
+  .addBatch({
+    'no quotes': {
+      topic: 'text without quotes',
+      iterator: function (topic) {
+        var index = 0;
+        new QuoteScanner(topic).each(function iterator() { index++; });
+
+        assert.equal(0, index);
+      }
+    },
+    'one single quote': {
+      topic: 'text with \'one quote\'!',
+      iterator: function (topic) {
+        var index = 0;
+        new QuoteScanner(topic).each(function iterator(match, tokensSoFar, nextStart) {
+          index++;
+
+          assert.equal('\'one quote\'', match);
+          assert.deepEqual(['text with '], tokensSoFar);
+          assert.equal(10, nextStart);
+        });
+
+        assert.equal(1, index);
+      }
+    },
+    'one double quote': {
+      topic: 'text with "one quote"!',
+      iterator: function (topic) {
+        var index = 0;
+        new QuoteScanner(topic).each(function iterator(match, tokensSoFar, nextStart) {
+          index++;
+
+          assert.equal('"one quote"', match);
+          assert.deepEqual(['text with '], tokensSoFar);
+          assert.equal(10, nextStart);
+        });
+
+        assert.equal(1, index);
+      }
+    },
+    'mixed quotes': {
+      topic: 'text with "one \'quote\'"!',
+      iterator: function (topic) {
+        var index = 0;
+        new QuoteScanner(topic).each(function iterator(match, tokensSoFar, nextStart) {
+          index++;
+
+          assert.equal('"one \'quote\'"', match);
+          assert.deepEqual(['text with '], tokensSoFar);
+          assert.equal(10, nextStart);
+        });
+
+        assert.equal(1, index);
+      }
+    },
+    'escaped quotes': {
+      topic: 'text with "one \\"quote"!',
+      iterator: function (topic) {
+        var index = 0;
+        new QuoteScanner(topic).each(function iterator(match, tokensSoFar, nextStart) {
+          index++;
+
+          assert.equal('"one \\"quote"', match);
+          assert.deepEqual(['text with '], tokensSoFar);
+          assert.equal(10, nextStart);
+        });
+
+        assert.equal(1, index);
+      }
+    },
+    'two quotes': {
+      topic: 'text with "one \\"quote" and \'another one\'!',
+      iterator: function (topic) {
+        var index = 0;
+        new QuoteScanner(topic).each(function iterator(match, tokensSoFar, nextStart) {
+          index++;
+
+          if (index == 1) {
+            assert.equal('"one \\"quote"', match);
+            assert.deepEqual(['text with '], tokensSoFar);
+            assert.equal(10, nextStart);
+          } else {
+            assert.equal('\'another one\'', match);
+            assert.deepEqual(['text with ', ' and '], tokensSoFar);
+            assert.equal(28, nextStart);
+          }
+        });
+
+        assert.equal(2, index);
+      }
+    }
+  })
+  .export(module);