12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- 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;
- });
|