mirror of https://github.com/xwiki-labs/cryptpad
66 lines
2.0 KiB
JavaScript
66 lines
2.0 KiB
JavaScript
// SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
define([
|
|
'/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;
|
|
});
|