|
|
define([ '/bower_components/chainpad/chainpad.dist.js',], function (ChainPad) { var Diff = ChainPad.Diff;
var isSpace = function (S, i) { return /^\s$/.test(S.charAt(i)); };
var leadingBoundary = function (S, offset) { if (/\s/.test(S.charAt(offset))) { return offset; } while (offset > 0) { offset--; if (isSpace(S, offset)) { offset++; break; } } return offset; };
var trailingBoundary = function (S, offset) { if (isSpace(S, offset)) { return offset; } while (offset < S.length && !/\s/.test(S.charAt(offset))) { offset++; } return offset; };
var opsToWords = function (previous, current) { var output = []; Diff.diff(previous, current).forEach(function (op) { // ignore deleted sections...
var offset = op.offset; var toInsert = op.toInsert;
// given an operation, check whether it is a word fragment,
// if it is, expand it to its word boundaries
var first = current.slice(leadingBoundary(current, offset), offset); var last = current.slice(offset + toInsert.length, trailingBoundary(current, offset + toInsert.length));
var result = first + toInsert + last; // concat-in-place
Array.prototype.push.apply(output, result.split(/\s+/)); }); return output.filter(Boolean); };
var runningDiff = function (getter, f, time) { var last = getter(); // first time through, send all the words :D
f(opsToWords("", last)); return setInterval(function () { var current = getter();
// find inserted words...
var words = opsToWords(last, current); last = current; f(words); }, time); };
return runningDiff;});
|