cledit refactoring

This commit is contained in:
benweet 2018-02-17 11:18:30 +00:00
parent f0721c9405
commit d57d2bb969
17 changed files with 430 additions and 397 deletions

View File

@ -4,7 +4,7 @@
<script>
import Prism from 'prismjs';
import cledit from '../libs/cledit';
import cledit from '../services/cledit';
export default {
props: ['value', 'lang', 'disabled'],

View File

@ -34,7 +34,7 @@
<script>
import { mapState } from 'vuex';
import editorSvc from '../services/editorSvc';
import cledit from '../libs/cledit';
import cledit from '../services/cledit';
import store from '../store';
import EditorClassApplier from './common/EditorClassApplier';

View File

@ -1,4 +1,4 @@
import cledit from '../../libs/cledit';
import cledit from '../../services/cledit';
import editorSvc from '../../services/editorSvc';
import utils from '../../services/utils';

View File

@ -1,4 +1,4 @@
import cledit from '../../libs/cledit';
import cledit from '../../services/cledit';
import editorSvc from '../../services/editorSvc';
import utils from '../../services/utils';

View File

@ -24,7 +24,7 @@
import { mapGetters, mapMutations, mapActions } from 'vuex';
import Prism from 'prismjs';
import UserImage from '../UserImage';
import cledit from '../../libs/cledit';
import cledit from '../../services/cledit';
import editorSvc from '../../services/editorSvc';
import markdownConversionSvc from '../../services/markdownConversionSvc';
import utils from '../../services/utils';

View File

@ -37,15 +37,6 @@ function cledit(contentElt, scrollEltOpt) {
let lastTextContent = getTextContent();
const highlighter = new cledit.Highlighter(editor);
let sectionList;
function parseSections(content, isInit) {
sectionList = highlighter.parseSections(content, isInit);
editor.$allElements = Array.prototype.slice
.call(contentElt.querySelectorAll('.cledit-section *'));
return sectionList;
}
/* eslint-disable new-cap */
const diffMatchPatch = new DiffMatchPatch();
/* eslint-enable new-cap */
@ -152,7 +143,11 @@ function cledit(contentElt, scrollEltOpt) {
}, 10);
let watcher;
let skipSaveSelection;
function checkContentChange(mutations) {
if (contentElt.textContent.indexOf('.') >= 0) {
debugger;
}
watcher.noWatch(() => {
const removedSections = [];
const modifiedSections = [];
@ -186,9 +181,13 @@ function cledit(contentElt, scrollEltOpt) {
marker.adjustOffset(diffs);
});
selectionMgr.saveSelectionState();
const parsedSections = parseSections(newTextContent);
editor.$trigger('contentChanged', newTextContent, diffs, parsedSections);
if (!skipSaveSelection) {
selectionMgr.saveSelectionState();
}
skipSaveSelection = false;
const sectionList = highlighter.parseSections(newTextContent);
editor.$trigger('contentChanged', newTextContent, diffs, sectionList);
if (!ignoreUndo) {
undoMgr.addDiffs(lastTextContent, newTextContent, diffs);
undoMgr.setDefaultMode('typing');
@ -270,12 +269,12 @@ function cledit(contentElt, scrollEltOpt) {
contentElt.addEventListener('keydown', keydownHandler((evt) => {
selectionMgr.saveSelectionState();
adjustCursorPosition();
// Perform keystroke
let contentChanging = false;
const textContent = getTextContent();
const min = Math.min(selectionMgr.selectionStart, selectionMgr.selectionEnd);
const max = Math.max(selectionMgr.selectionStart, selectionMgr.selectionEnd);
let min = Math.min(selectionMgr.selectionStart, selectionMgr.selectionEnd);
let max = Math.max(selectionMgr.selectionStart, selectionMgr.selectionEnd);
const state = {
before: textContent.slice(0, min),
after: textContent.slice(max),
@ -286,15 +285,26 @@ function cledit(contentElt, scrollEltOpt) {
if (!keystroke.handler(evt, state, editor)) {
return false;
}
editor.setContent(state.before + state.selection + state.after, false, min);
const min1 = state.before.length;
const max1 = min + state.selection.length;
const newContent = state.before + state.selection + state.after;
if (newContent !== getTextContent()) {
editor.setContent(newContent, false, min);
contentChanging = true;
skipSaveSelection = true;
}
min = state.before.length;
max = min + state.selection.length;
selectionMgr.setSelectionStartEnd(
state.isBackwardSelection ? max1 : min1,
state.isBackwardSelection ? min : max1,
state.isBackwardSelection ? max : min,
state.isBackwardSelection ? min : max,
!contentChanging, // Expect a restore selection on mutation event
);
return true;
});
if (!contentChanging) {
// Optimization to avoid saving selection
adjustCursorPosition();
}
}));
contentElt.addEventListener('compositionstart', () => {
@ -406,8 +416,8 @@ function cledit(contentElt, scrollEltOpt) {
}
}
const parsedSections = parseSections(lastTextContent, true);
editor.$trigger('contentChanged', lastTextContent, [0, lastTextContent], parsedSections);
const sectionList = highlighter.parseSections(lastTextContent, true);
editor.$trigger('contentChanged', lastTextContent, [0, lastTextContent], sectionList);
if (options.selectionStart !== undefined && options.selectionEnd !== undefined) {
editor.setSelection(options.selectionStart, options.selectionEnd);
} else {
@ -423,4 +433,4 @@ function cledit(contentElt, scrollEltOpt) {
return editor;
}
module.exports = cledit;
export default cledit;

View File

@ -11,7 +11,6 @@ function createStyleSheet(document) {
}
function Highlighter(editor) {
const self = this;
cledit.Utils.createEventHooks(this);
if (!styleElts.cl_some(styleElt => document.head.contains(styleElt))) {
@ -63,7 +62,7 @@ function Highlighter(editor) {
}
this.parseSections = (content, isInit) => {
if (this.isComposing) {
if (true) {
return sectionList;
}
@ -133,14 +132,14 @@ function Highlighter(editor) {
sectionList = leftSections.concat(modifiedSections).concat(rightSections);
}
function highlight(section) {
const highlight = (section) => {
const html = editor.options.sectionHighlighter(section).replace(/\n/g, lfHtml);
const sectionElt = document.createElement('div');
sectionElt.className = 'cledit-section';
sectionElt.innerHTML = html;
section.setElement(sectionElt);
self.$trigger('sectionHighlighted', section);
}
this.$trigger('sectionHighlighted', section);
};
const newSectionEltList = document.createDocumentFragment();
modifiedSections.cl_each((section) => {
@ -183,7 +182,8 @@ function Highlighter(editor) {
childNode = nextNode;
}
this.addTrailingNode();
self.$trigger('highlighted');
this.$trigger('highlighted');
if (editor.selectionMgr.hasFocus()) {
editor.selectionMgr.restoreSelection();
editor.selectionMgr.updateCursorCoordinates();

View File

@ -6,7 +6,6 @@ function SelectionMgr(editor) {
const scrollElt = editor.$scrollElt;
cledit.Utils.createEventHooks(this);
const self = this;
let lastSelectionStart = 0;
let lastSelectionEnd = 0;
this.selectionStart = 0;
@ -28,7 +27,7 @@ function SelectionMgr(editor) {
return result;
};
this.createRange = function (start, end) {
this.createRange = (start, end) => {
const range = document.createRange();
const startContainer = isNaN(start) ? start : this.findContainer(start < 0 ? 0 : start);
let endContainer = startContainer;
@ -72,14 +71,14 @@ function SelectionMgr(editor) {
adjustScroll = false;
});
this.updateCursorCoordinates = function (adjustScrollParam) {
this.updateCursorCoordinates = (adjustScrollParam) => {
adjustScroll = adjustScroll || adjustScrollParam;
debouncedUpdateCursorCoordinates();
};
let oldSelectionRange;
function checkSelection(selectionRange) {
const checkSelection = (selectionRange) => {
if (!oldSelectionRange ||
oldSelectionRange.startContainer !== selectionRange.startContainer ||
oldSelectionRange.startOffset !== selectionRange.startOffset ||
@ -87,11 +86,11 @@ function SelectionMgr(editor) {
oldSelectionRange.endOffset !== selectionRange.endOffset
) {
oldSelectionRange = selectionRange;
self.$trigger('selectionChanged', self.selectionStart, self.selectionEnd, selectionRange);
this.$trigger('selectionChanged', this.selectionStart, this.selectionEnd, selectionRange);
return true;
}
return false;
}
};
this.hasFocus = () => contentElt === document.activeElement;
@ -118,19 +117,22 @@ function SelectionMgr(editor) {
};
const saveLastSelection = debounce(() => {
lastSelectionStart = self.selectionStart;
lastSelectionEnd = self.selectionEnd;
lastSelectionStart = this.selectionStart;
lastSelectionEnd = this.selectionEnd;
}, 50);
function setSelection(start = self.selectionStart, end = this.selectionEnd) {
self.selectionStart = start < 0 ? 0 : start;
self.selectionEnd = end < 0 ? 0 : end;
const setSelection = (start = this.selectionStart, end = this.selectionEnd) => {
this.selectionStart = start < 0 ? 0 : start;
this.selectionEnd = end < 0 ? 0 : end;
saveLastSelection();
}
};
this.setSelectionStartEnd = (start, end) => {
this.setSelectionStartEnd = (start, end, restoreSelection = true) => {
setSelection(start, end);
return this.hasFocus() && this.restoreSelection();
if (restoreSelection && this.hasFocus()) {
return this.restoreSelection();
}
return null;
};
this.saveSelectionState = (() => {
@ -217,182 +219,199 @@ function SelectionMgr(editor) {
if (childA === childB) {
// This shouldn't be possible
throw module.createError('comparePoints got to case 4 and childA and childB are the same!');
} else {
n = root.firstChild;
while (n) {
if (n === childA) {
return -1;
} else if (n === childB) {
return 1;
}
n = n.nextSibling;
}
}
n = root.firstChild;
while (n) {
if (n === childA) {
return -1;
} else if (n === childB) {
return 1;
}
n = n.nextSibling;
}
return 0;
}
function save() {
const save = () => {
let result;
if (self.hasFocus()) {
const selectionStart = self.selectionStart;
const selectionEnd = self.selectionEnd;
if (this.hasFocus()) {
let selectionStart = this.selectionStart;
let selectionEnd = this.selectionEnd;
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const selectionRange = selection.getRangeAt(0);
const node = selectionRange.startContainer;
if ((contentElt.compareDocumentPosition(node) & window.Node.DOCUMENT_POSITION_CONTAINED_BY) || contentElt === node) {
var offset = selectionRange.startOffset
let node = selectionRange.startContainer;
// eslint-disable-next-line no-bitwise
if ((contentElt.compareDocumentPosition(node)
& window.Node.DOCUMENT_POSITION_CONTAINED_BY)
|| contentElt === node
) {
let offset = selectionRange.startOffset;
if (node.firstChild && offset > 0) {
node = node.childNodes[offset - 1]
offset = node.textContent.length
node = node.childNodes[offset - 1];
offset = node.textContent.length;
}
var container = node
let container = node;
while (node !== contentElt) {
while ((node = node.previousSibling)) {
offset += (node.textContent || '').length
node = node.previousSibling;
while (node) {
offset += (node.textContent || '').length;
node = node.previousSibling;
}
node = container = container.parentNode
node = container.parentNode;
container = node;
}
var selectionText = selectionRange + ''
let selectionText = `${selectionRange}`;
// Fix end of line when only br is selected
var brElt = selectionRange.endContainer.firstChild
const brElt = selectionRange.endContainer.firstChild;
if (brElt && brElt.tagName === 'BR' && selectionRange.endOffset === 1) {
selectionText += '\n'
selectionText += '\n';
}
if (comparePoints(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset) === 1) {
selectionStart = offset + selectionText.length
selectionEnd = offset
if (comparePoints(
selection.anchorNode,
selection.anchorOffset,
selection.focusNode,
selection.focusOffset) === 1
) {
selectionStart = offset + selectionText.length;
selectionEnd = offset;
} else {
selectionStart = offset
selectionEnd = offset + selectionText.length
selectionStart = offset;
selectionEnd = offset + selectionText.length;
}
if (selectionStart === selectionEnd && selectionStart === editor.getContent().length) {
// If cursor is after the trailingNode
selectionStart = --selectionEnd
result = self.setSelectionStartEnd(selectionStart, selectionEnd)
selectionEnd -= 1;
selectionStart = selectionEnd;
result = this.setSelectionStartEnd(selectionStart, selectionEnd);
} else {
setSelection(selectionStart, selectionEnd)
result = checkSelection(selectionRange)
result = result || lastSelectionStart !== self.selectionStart // selectionRange doesn't change when selection is at the start of a section
setSelection(selectionStart, selectionEnd);
result = checkSelection(selectionRange);
// selectionRange doesn't change when selection is at the start of a section
result = result || lastSelectionStart !== this.selectionStart;
}
}
}
}
return result
}
return result;
};
function saveCheckChange() {
return save() && (lastSelectionStart !== self.selectionStart || lastSelectionEnd !== self.selectionEnd)
}
const saveCheckChange = () => save() && (
lastSelectionStart !== this.selectionStart || lastSelectionEnd !== this.selectionEnd);
var nextTickAdjustScroll = false
var debouncedSave = debounce(function () {
self.updateCursorCoordinates(saveCheckChange() && nextTickAdjustScroll)
// In some cases we have to wait a little longer to see the selection change (Cmd+A on Chrome OSX)
longerDebouncedSave()
})
var longerDebouncedSave = debounce(function () {
self.updateCursorCoordinates(saveCheckChange() && nextTickAdjustScroll)
nextTickAdjustScroll = false
}, 10)
let nextTickAdjustScroll = false;
const longerDebouncedSave = debounce(() => {
this.updateCursorCoordinates(saveCheckChange() && nextTickAdjustScroll);
nextTickAdjustScroll = false;
}, 10);
const debouncedSave = debounce(() => {
this.updateCursorCoordinates(saveCheckChange() && nextTickAdjustScroll);
// In some cases we have to wait a little longer to see the
// selection change (Cmd+A on Chrome OSX)
longerDebouncedSave();
});
return function (debounced, adjustScroll, forceAdjustScroll) {
return (debounced, adjustScrollParam, forceAdjustScroll) => {
if (forceAdjustScroll) {
lastSelectionStart = undefined
lastSelectionEnd = undefined
lastSelectionStart = undefined;
lastSelectionEnd = undefined;
}
if (debounced) {
nextTickAdjustScroll = nextTickAdjustScroll || adjustScroll
return debouncedSave()
nextTickAdjustScroll = nextTickAdjustScroll || adjustScrollParam;
debouncedSave();
} else {
save()
save();
}
}
})()
};
})();
this.getSelectedText = function () {
var min = Math.min(this.selectionStart, this.selectionEnd)
var max = Math.max(this.selectionStart, this.selectionEnd)
return editor.getContent().substring(min, max)
}
this.getSelectedText = () => {
const min = Math.min(this.selectionStart, this.selectionEnd);
const max = Math.max(this.selectionStart, this.selectionEnd);
return editor.getContent().substring(min, max);
};
this.getCoordinates = function (inputOffset, container, offsetInContainer) {
this.getCoordinates = (inputOffset, containerParam, offsetInContainerParam) => {
let container = containerParam;
let offsetInContainer = offsetInContainerParam;
if (!container) {
var offset = this.findContainer(inputOffset)
container = offset.container
offsetInContainer = offset.offsetInContainer
const offset = this.findContainer(inputOffset);
container = offset.container;
offsetInContainer = offset.offsetInContainer;
}
var containerElt = container
let containerElt = container;
if (!containerElt.hasChildNodes()) {
containerElt = container.parentNode
containerElt = container.parentNode;
}
var isInvisible = false
var index = editor.$allElements.indexOf(containerElt)
while (containerElt.offsetHeight === 0 && index > 0) {
isInvisible = true
containerElt = editor.$allElements[--index]
let isInvisible = false;
while (containerElt.offsetHeight === 0) {
isInvisible = true;
if (containerElt.previousSibling) {
containerElt = containerElt.previousSibling;
} else {
containerElt = containerElt.parentNode;
}
}
var rect
var contentRect
var left = 'left'
let rect;
let left = 'left';
if (isInvisible || container.textContent === '\n') {
rect = containerElt.getBoundingClientRect()
rect = containerElt.getBoundingClientRect();
} else {
var selectedChar = editor.getContent()[inputOffset]
var startOffset = {
container: container,
offsetInContainer: offsetInContainer
}
var endOffset = {
container: container,
offsetInContainer: offsetInContainer
}
const selectedChar = editor.getContent()[inputOffset];
let startOffset = {
container,
offsetInContainer,
};
let endOffset = {
container,
offsetInContainer,
};
if (inputOffset > 0 && (selectedChar === undefined || selectedChar === '\n')) {
left = 'right'
left = 'right';
if (startOffset.offsetInContainer === 0) {
// Need to calculate offset-1
startOffset = inputOffset - 1
startOffset = inputOffset - 1;
} else {
startOffset.offsetInContainer -= 1
startOffset.offsetInContainer -= 1;
}
} else if (endOffset.offsetInContainer === container.textContent.length) {
// Need to calculate offset+1
endOffset = inputOffset + 1;
} else {
if (endOffset.offsetInContainer === container.textContent.length) {
// Need to calculate offset+1
endOffset = inputOffset + 1
} else {
endOffset.offsetInContainer += 1
}
endOffset.offsetInContainer += 1;
}
var range = this.createRange(startOffset, endOffset)
rect = range.getBoundingClientRect()
const range = this.createRange(startOffset, endOffset);
rect = range.getBoundingClientRect();
}
contentRect = contentElt.getBoundingClientRect()
const contentRect = contentElt.getBoundingClientRect();
return {
top: Math.round(rect.top - contentRect.top + contentElt.scrollTop),
top: Math.round((rect.top - contentRect.top) + contentElt.scrollTop),
height: Math.round(rect.height),
left: Math.round(rect[left] - contentRect.left + contentElt.scrollLeft)
}
}
left: Math.round((rect[left] - contentRect.left) + contentElt.scrollLeft),
};
};
this.getClosestWordOffset = function (offset) {
var offsetStart = 0
var offsetEnd = 0
var nextOffset = 0
editor.getContent().split(/\s/).cl_some(function (word) {
this.getClosestWordOffset = (offset) => {
let offsetStart = 0;
let offsetEnd = 0;
let nextOffset = 0;
editor.getContent().split(/\s/).cl_some((word) => {
if (word) {
offsetStart = nextOffset
offsetEnd = nextOffset + word.length
offsetStart = nextOffset;
offsetEnd = nextOffset + word.length;
if (offsetEnd > offset) {
return true
return true;
}
}
nextOffset += word.length + 1
})
nextOffset += word.length + 1;
return false;
});
return {
start: offsetStart,
end: offsetEnd
}
}
end: offsetEnd,
};
};
}
cledit.SelectionMgr = SelectionMgr
cledit.SelectionMgr = SelectionMgr;

View File

@ -1,178 +1,176 @@
var DiffMatchPatch = require('diff-match-patch');
var cledit = require('./cleditCore')
import DiffMatchPatch from 'diff-match-patch';
import cledit from './cleditCore';
function UndoMgr(editor) {
cledit.Utils.createEventHooks(this)
cledit.Utils.createEventHooks(this);
/* eslint-disable new-cap */
var diffMatchPatch = new DiffMatchPatch()
const diffMatchPatch = new DiffMatchPatch();
/* eslint-enable new-cap */
var self = this
var selectionMgr
var undoStack = []
var redoStack = []
var currentState
var previousPatches = []
var currentPatches = []
var debounce = cledit.Utils.debounce
const self = this;
let selectionMgr;
const undoStack = [];
const redoStack = [];
let currentState;
let previousPatches = [];
let currentPatches = [];
const debounce = cledit.Utils.debounce;
self.options = {
this.options = {
undoStackMaxSize: 200,
bufferStateUntilIdle: 1000,
patchHandler: {
makePatches: function (oldContent, newContent, diffs) {
return diffMatchPatch.patch_make(oldContent, diffs)
makePatches(oldContent, newContent, diffs) {
return diffMatchPatch.patch_make(oldContent, diffs);
},
applyPatches: function (patches, content) {
return diffMatchPatch.patch_apply(patches, content)[0]
applyPatches(patches, content) {
return diffMatchPatch.patch_apply(patches, content)[0];
},
reversePatches: function (patches) {
patches = diffMatchPatch.patch_deepCopy(patches).reverse()
patches.cl_each(function (patch) {
patch.diffs.cl_each(function (diff) {
diff[0] = -diff[0]
})
})
return patches
}
}
}
function State() { }
reversePatches(patches) {
const reversedPatches = diffMatchPatch.patch_deepCopy(patches).reverse();
reversedPatches.cl_each((patch) => {
patch.diffs.cl_each((diff) => {
diff[0] = -diff[0];
});
});
return reversedPatches;
},
},
};
let stateMgr;
function StateMgr() {
var currentTime, lastTime
var lastMode
let currentTime;
let lastTime;
let lastMode;
this.isBufferState = function () {
currentTime = Date.now()
this.isBufferState = () => {
currentTime = Date.now();
return this.currentMode !== 'single' &&
this.currentMode === lastMode &&
currentTime - lastTime < self.options.bufferStateUntilIdle
}
currentTime - lastTime < self.options.bufferStateUntilIdle;
};
this.setDefaultMode = function (mode) {
this.currentMode = this.currentMode || mode
}
this.setDefaultMode = (mode) => {
this.currentMode = this.currentMode || mode;
};
this.resetMode = function () {
stateMgr.currentMode = undefined
lastMode = undefined
}
this.resetMode = () => {
stateMgr.currentMode = undefined;
lastMode = undefined;
};
this.saveMode = function () {
lastMode = this.currentMode
this.currentMode = undefined
lastTime = currentTime
this.saveMode = () => {
lastMode = this.currentMode;
this.currentMode = undefined;
lastTime = currentTime;
};
}
class State {
addToUndoStack() {
undoStack.push(this);
this.patches = previousPatches;
previousPatches = [];
}
addToRedoStack() {
redoStack.push(this);
this.patches = previousPatches;
previousPatches = [];
}
}
function addToStack(stack) {
return function () {
stack.push(this)
this.patches = previousPatches
previousPatches = []
}
}
stateMgr = new StateMgr();
this.setCurrentMode = (mode) => {
stateMgr.currentMode = mode;
};
this.setDefaultMode = stateMgr.setDefaultMode.cl_bind(stateMgr);
State.prototype.addToUndoStack = addToStack(undoStack)
State.prototype.addToRedoStack = addToStack(redoStack)
var stateMgr = new StateMgr()
this.setCurrentMode = function (mode) {
stateMgr.currentMode = mode
}
this.setDefaultMode = stateMgr.setDefaultMode.cl_bind(stateMgr)
this.addDiffs = function (oldContent, newContent, diffs) {
var patches = self.options.patchHandler.makePatches(oldContent, newContent, diffs)
currentPatches.push.apply(currentPatches, patches)
}
this.addDiffs = (oldContent, newContent, diffs) => {
const patches = this.options.patchHandler.makePatches(oldContent, newContent, diffs);
patches.cl_each(patch => currentPatches.push(patch));
};
function saveCurrentPatches() {
// Move currentPatches into previousPatches
Array.prototype.push.apply(previousPatches, currentPatches)
currentPatches = []
Array.prototype.push.apply(previousPatches, currentPatches);
currentPatches = [];
}
this.saveState = debounce(function () {
redoStack.length = 0
this.saveState = debounce(() => {
redoStack.length = 0;
if (!stateMgr.isBufferState()) {
currentState.addToUndoStack()
currentState.addToUndoStack();
// Limit the size of the stack
while (undoStack.length > self.options.undoStackMaxSize) {
undoStack.shift()
while (undoStack.length > this.options.undoStackMaxSize) {
undoStack.shift();
}
}
saveCurrentPatches()
currentState = new State()
stateMgr.saveMode()
self.$trigger('undoStateChange')
})
saveCurrentPatches();
currentState = new State();
stateMgr.saveMode();
this.$trigger('undoStateChange');
});
this.canUndo = function () {
return !!undoStack.length
}
this.canUndo = () => !!undoStack.length;
this.canRedo = () => !!redoStack.length;
this.canRedo = function () {
return !!redoStack.length
}
function restoreState(patches, isForward) {
const restoreState = (patchesParam, isForward) => {
let patches = patchesParam;
// Update editor
var content = editor.getContent()
const content = editor.getContent();
if (!isForward) {
patches = self.options.patchHandler.reversePatches(patches)
patches = this.options.patchHandler.reversePatches(patches);
}
var newContent = self.options.patchHandler.applyPatches(patches, content)
var newContentText = newContent.text || newContent
var range = editor.setContent(newContentText, true)
var selection = newContent.selection || {
const newContent = this.options.patchHandler.applyPatches(patches, content);
const newContentText = newContent.text || newContent;
const range = editor.setContent(newContentText, true);
const selection = newContent.selection || {
start: range.end,
end: range.end
}
end: range.end,
};
selectionMgr.setSelectionStartEnd(selection.start, selection.end)
selectionMgr.updateCursorCoordinates(true)
selectionMgr.setSelectionStartEnd(selection.start, selection.end);
selectionMgr.updateCursorCoordinates(true);
stateMgr.resetMode()
self.$trigger('undoStateChange')
editor.adjustCursorPosition()
}
stateMgr.resetMode();
this.$trigger('undoStateChange');
editor.adjustCursorPosition();
};
this.undo = function () {
var state = undoStack.pop()
this.undo = () => {
const state = undoStack.pop();
if (!state) {
return
return;
}
saveCurrentPatches()
currentState.addToRedoStack()
restoreState(currentState.patches)
previousPatches = state.patches
currentState = state
}
saveCurrentPatches();
currentState.addToRedoStack();
restoreState(currentState.patches);
previousPatches = state.patches;
currentState = state;
};
this.redo = function () {
var state = redoStack.pop()
this.redo = () => {
const state = redoStack.pop();
if (!state) {
return
return;
}
currentState.addToUndoStack()
restoreState(state.patches, true)
previousPatches = state.patches
currentState = state
}
currentState.addToUndoStack();
restoreState(state.patches, true);
previousPatches = state.patches;
currentState = state;
};
this.init = function (options) {
self.options.cl_extend(options || {})
selectionMgr = editor.selectionMgr
this.init = (options) => {
this.options.cl_extend(options || {});
selectionMgr = editor.selectionMgr;
if (!currentState) {
currentState = new State()
currentState = new State();
}
}
};
}
cledit.UndoMgr = UndoMgr
cledit.UndoMgr = UndoMgr;

View File

@ -1,123 +1,128 @@
var cledit = require('./cleditCore')
import cledit from './cleditCore';
var Utils = {
const Utils = {
isGecko: 'MozAppearance' in document.documentElement.style,
isWebkit: 'WebkitAppearance' in document.documentElement.style,
isMsie: 'msTransform' in document.documentElement.style,
isMac: navigator.userAgent.indexOf('Mac OS X') !== -1
}
isMac: navigator.userAgent.indexOf('Mac OS X') !== -1,
};
// Faster than setTimeout(0). Credit: https://github.com/stefanpenner/es6-promise
Utils.defer = (function () {
var queue = new Array(1000)
var queueLength = 0
Utils.defer = (() => {
const queue = new Array(1000);
let queueLength = 0;
function flush() {
for (var i = 0; i < queueLength; i++) {
for (let i = 0; i < queueLength; i += 1) {
try {
queue[i]()
queue[i]();
} catch (e) {
console.error(e.message, e.stack)
// eslint-disable-next-line no-console
console.error(e.message, e.stack);
}
queue[i] = undefined
queue[i] = undefined;
}
queueLength = 0
queueLength = 0;
}
var iterations = 0
var observer = new window.MutationObserver(flush)
var node = document.createTextNode('')
observer.observe(node, { characterData: true })
let iterations = 0;
const observer = new window.MutationObserver(flush);
const node = document.createTextNode('');
observer.observe(node, { characterData: true });
return function (fn) {
queue[queueLength++] = fn
return (fn) => {
queue[queueLength] = fn;
queueLength += 1;
if (queueLength === 1) {
node.data = (iterations = ++iterations % 2)
iterations = (iterations + 1) % 2;
node.data = iterations;
}
}
})()
};
})();
Utils.debounce = function (func, wait) {
var timeoutId, isExpected
Utils.debounce = (func, wait) => {
let timeoutId;
let isExpected;
return wait
? function () {
clearTimeout(timeoutId)
timeoutId = setTimeout(func, wait)
? () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(func, wait);
}
: function () {
: () => {
if (!isExpected) {
isExpected = true
Utils.defer(function () {
isExpected = false
func()
})
isExpected = true;
Utils.defer(() => {
isExpected = false;
func();
});
}
}
}
};
};
Utils.createEventHooks = function (object) {
var listenerMap = Object.create(null)
object.$trigger = function (eventType) {
var listeners = listenerMap[eventType]
Utils.createEventHooks = (object) => {
const listenerMap = Object.create(null);
object.$trigger = (eventType, ...args) => {
const listeners = listenerMap[eventType];
if (listeners) {
var args = Array.prototype.slice.call(arguments, 1)
listeners.cl_each(function (listener) {
listeners.cl_each((listener) => {
try {
listener.apply(object, args)
listener.apply(object, args);
} catch (e) {
console.error(e.message, e.stack)
console.error(e.message, e.stack);
}
})
});
}
}
object.on = function (eventType, listener) {
var listeners = listenerMap[eventType]
};
object.on = (eventType, listener) => {
let listeners = listenerMap[eventType];
if (!listeners) {
listeners = []
listenerMap[eventType] = listeners
listeners = [];
listenerMap[eventType] = listeners;
}
listeners.push(listener)
}
object.off = function (eventType, listener) {
var listeners = listenerMap[eventType]
listeners.push(listener);
};
object.off = (eventType, listener) => {
const listeners = listenerMap[eventType];
if (listeners) {
var index = listeners.indexOf(listener)
if (~index) {
listeners.splice(index, 1)
const index = listeners.indexOf(listener);
if (index !== -1) {
listeners.splice(index, 1);
}
}
}
}
};
};
Utils.findContainer = function (elt, offset) {
var containerOffset = 0
var container
Utils.findContainer = (elt, offset) => {
let containerOffset = 0;
let container;
let child = elt;
do {
container = elt
elt = elt.firstChild
if (elt) {
container = child;
child = child.firstChild;
if (child) {
do {
var len = elt.textContent.length
const len = child.textContent.length;
if (containerOffset <= offset && containerOffset + len > offset) {
break
break;
}
containerOffset += len
} while ((elt = elt.nextSibling))
containerOffset += len;
child = child.nextSibling;
} while (child);
}
} while (elt && elt.firstChild && elt.nodeType !== 3)
} while (child && child.firstChild && child.nodeType !== 3);
if (elt) {
if (child) {
return {
container: elt,
offsetInContainer: offset - containerOffset
}
container: child,
offsetInContainer: offset - containerOffset,
};
}
while (container.lastChild) {
container = container.lastChild
container = container.lastChild;
}
return {
container: container,
offsetInContainer: container.nodeType === 3 ? container.textContent.length : 0
}
}
container,
offsetInContainer: container.nodeType === 3 ? container.textContent.length : 0,
};
};
cledit.Utils = Utils
cledit.Utils = Utils;

View File

@ -1,33 +1,34 @@
var cledit = require('./cleditCore')
import cledit from './cleditCore';
function Watcher(editor, listener) {
this.isWatching = false
var contentObserver
this.startWatching = function () {
this.stopWatching()
this.isWatching = true
contentObserver = new window.MutationObserver(listener)
this.isWatching = false;
let contentObserver;
this.startWatching = () => {
this.stopWatching();
this.isWatching = true;
contentObserver = new window.MutationObserver(listener);
contentObserver.observe(editor.$contentElt, {
childList: true,
subtree: true,
characterData: true
})
}
this.stopWatching = function () {
characterData: true,
});
};
this.stopWatching = () => {
if (contentObserver) {
contentObserver.disconnect()
contentObserver = undefined
contentObserver.disconnect();
contentObserver = undefined;
}
this.isWatching = false
}
this.noWatch = function (cb) {
this.isWatching = false;
};
this.noWatch = (cb) => {
if (this.isWatching === true) {
this.stopWatching()
cb()
return this.startWatching()
this.stopWatching();
cb();
this.startWatching();
} else {
cb();
}
cb()
}
};
}
cledit.Watcher = Watcher
cledit.Watcher = Watcher;

View File

@ -2,7 +2,7 @@ import Vue from 'vue';
import DiffMatchPatch from 'diff-match-patch';
import Prism from 'prismjs';
import markdownItPandocRenderer from 'markdown-it-pandoc-renderer';
import cledit from '../libs/cledit';
import cledit from './cledit';
import pagedown from '../libs/pagedown';
import htmlSanitizer from '../libs/htmlSanitizer';
import markdownConversionSvc from './markdownConversionSvc';

View File

@ -1,5 +1,5 @@
import DiffMatchPatch from 'diff-match-patch';
import cledit from '../libs/cledit';
import cledit from './cledit';
import utils from './utils';
import diffUtils from './diffUtils';
import store from '../store';

View File

@ -1,5 +1,5 @@
import DiffMatchPatch from 'diff-match-patch';
import cledit from '../libs/cledit';
import cledit from './cledit';
import animationSvc from './animationSvc';
import store from '../store';

View File

@ -1,4 +1,4 @@
import cledit from '../../libs/cledit';
import cledit from '../cledit';
import editorSvc from '../editorSvc';
const Keystroke = cledit.Keystroke;

View File

@ -2,7 +2,7 @@ import DiffMatchPatch from 'diff-match-patch';
import moduleTemplate from './moduleTemplate';
import empty from '../data/emptyContent';
import utils from '../services/utils';
import cledit from '../libs/cledit';
import cledit from '../services/cledit';
const diffMatchPatch = new DiffMatchPatch();

View File

@ -1,4 +1,4 @@
import createLogger from 'vuex/dist/logger';
// import createLogger from 'vuex/dist/logger';
import Vue from 'vue';
import Vuex from 'vuex';
import utils from '../services/utils';
@ -120,7 +120,7 @@ const store = new Vuex.Store({
},
},
strict: debug,
plugins: debug ? [createLogger()] : [],
// plugins: debug ? [createLogger()] : [],
});
setInterval(() => {