|
|
@@ -1584,119 +1584,5 @@ define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) {
|
|
|
};
|
|
|
});
|
|
|
|
|
|
- // This is some utility code to connect a CodeMirror editor
|
|
|
- // to a sharejs document.
|
|
|
- // It is heavily inspired from the Ace editor hook.
|
|
|
-
|
|
|
- // Convert a CodeMirror delta into an op understood by share.js
|
|
|
- var applyCMToShareJS = function applyCMToShareJS(editorDoc, delta, doc, fromUndo) {
|
|
|
- // CodeMirror deltas give a text replacement.
|
|
|
- // I tuned this operation a little bit, for speed.
|
|
|
- var startPos = 0; // Get character position from # of chars in each line.
|
|
|
- var i = 0; // i goes through all lines.
|
|
|
- // Compute the position from the shareJS snapshot because we are in the CodeMirror
|
|
|
- // change event, where the change has already been applied to the editorDoc
|
|
|
- var docLines = doc.snapshot.split('\n', delta.from.line) // only split the document as far as we need to
|
|
|
- while (i < delta.from.line) {
|
|
|
- startPos += docLines[i].length + 1; // Add 1 for '\n'
|
|
|
- i++;
|
|
|
- }
|
|
|
- startPos += delta.from.ch;
|
|
|
-
|
|
|
- // NOTE: Keep in sync with EditorWatchdogManager.
|
|
|
- if (delta.removed) {
|
|
|
- doc.del(startPos, delta.removed.join('\n').length, fromUndo);
|
|
|
- }
|
|
|
- if (delta.text) {
|
|
|
- return doc.insert(startPos, delta.text.join('\n'), fromUndo);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // Attach a CodeMirror editor to the document. The editor's contents are replaced
|
|
|
- // with the document's contents.
|
|
|
- // NOTE: When upgrading CM, make sure to check for new special cases of
|
|
|
- // origin prefixes as documented for `doc.setSelection`. We are using
|
|
|
- // a custom `origin: 'remote'` which may conflict.
|
|
|
- // Perma link of the docs at the time of writing this note:
|
|
|
- // https://web.archive.org/web/20201029163528/https://codemirror.net/doc/manual.html#selection_origin
|
|
|
- window.sharejs.extendDoc('attach_cm', function (editor, maxDocLength) {
|
|
|
- if (!this.provides.text) {
|
|
|
- throw new Error('Only text documents can be attached to CodeMirror2');
|
|
|
- }
|
|
|
-
|
|
|
- var sharedoc = this;
|
|
|
- var editorDoc = editor.getDoc();
|
|
|
-
|
|
|
- function check() {
|
|
|
- return window.setTimeout(function () {
|
|
|
- var editorText = editor.getValue();
|
|
|
- var otText = sharedoc.getText();
|
|
|
-
|
|
|
- if (editorText !== otText) {
|
|
|
- sharedoc.emit('error','Text does not match in CodeMirror')
|
|
|
- console.error('Text does not match!');
|
|
|
- console.error('editor: ' + editorText);
|
|
|
- return console.error('ot: ' + otText);
|
|
|
- }
|
|
|
- }
|
|
|
- // Removed editor.setValue here as it would cause recursive loops if
|
|
|
- // consistency check failed - because setting the value would trigger
|
|
|
- // the change event
|
|
|
- , 0);
|
|
|
- };
|
|
|
-
|
|
|
- onDelete(0, editor.getValue());
|
|
|
- onInsert(0, sharedoc.getText());
|
|
|
-
|
|
|
- check();
|
|
|
-
|
|
|
- // Listen for edits in CodeMirror.
|
|
|
- function editorListener(ed, change) {
|
|
|
- if (change.origin === 'remote') {
|
|
|
- // this change has been injected via sharejs
|
|
|
- return;
|
|
|
- }
|
|
|
- if (maxDocLength != null && editorDoc.getValue().length >= maxDocLength) {
|
|
|
- sharedoc.emit('error', new Error('document length is greater than maxDocLength'));
|
|
|
- return;
|
|
|
- }
|
|
|
- var fromUndo = (change.origin === 'undo')
|
|
|
- applyCMToShareJS(editorDoc, change, sharedoc, fromUndo);
|
|
|
- return check();
|
|
|
- };
|
|
|
-
|
|
|
- editorDoc.on('change', editorListener);
|
|
|
-
|
|
|
- function onInsert(pos, text) {
|
|
|
- // All the primitives we need are already in CM's API.
|
|
|
- // call signature: editor.replaceRange(text, from, to, origin)
|
|
|
- editor.replaceRange(text, editor.posFromIndex(pos), undefined, 'remote');
|
|
|
- // Clear CM's undo/redo history on remote edit. This prevents issues where
|
|
|
- // a user can accidentally remove another user's edits
|
|
|
- editor.clearHistory();
|
|
|
- return check();
|
|
|
- };
|
|
|
-
|
|
|
- function onDelete(pos, text) {
|
|
|
- var from = editor.posFromIndex(pos);
|
|
|
- var to = editor.posFromIndex(pos + text.length);
|
|
|
- editor.replaceRange('', from, to, 'remote');
|
|
|
- // Clear CM's undo/redo history on remote edit. This prevents issues where
|
|
|
- // a user can accidentally remove another user's edits
|
|
|
- editor.clearHistory()
|
|
|
- return check();
|
|
|
- };
|
|
|
-
|
|
|
- this.on('insert', onInsert);
|
|
|
- this.on('delete', onDelete);
|
|
|
-
|
|
|
- this.detach_cm = function () {
|
|
|
- this.removeListener('insert', onInsert);
|
|
|
- this.removeListener('delete', onDelete);
|
|
|
- editorDoc.off('change', editorListener);
|
|
|
- return delete this.detach_cm;
|
|
|
- };
|
|
|
- });
|
|
|
-
|
|
|
return window.sharejs;
|
|
|
});
|