@lexical/history
Advanced tools
Comparing version 0.7.8 to 0.7.9
@@ -21,10 +21,7 @@ /** | ||
const DELETE_CHARACTER_AFTER_SELECTION = 4; | ||
function getDirtyNodes(editorState, dirtyLeaves, dirtyElements) { | ||
const nodeMap = editorState._nodeMap; | ||
const nodes = []; | ||
for (const dirtyLeafKey of dirtyLeaves) { | ||
const dirtyLeaf = nodeMap.get(dirtyLeafKey); | ||
if (dirtyLeaf !== undefined) { | ||
@@ -34,3 +31,2 @@ nodes.push(dirtyLeaf); | ||
} | ||
for (const [dirtyElementKey, intentionallyMarkedAsDirty] of dirtyElements) { | ||
@@ -40,5 +36,3 @@ if (!intentionallyMarkedAsDirty) { | ||
} | ||
const dirtyElement = nodeMap.get(dirtyElementKey); | ||
if (dirtyElement !== undefined && !lexical.$isRootNode(dirtyElement)) { | ||
@@ -48,6 +42,4 @@ nodes.push(dirtyElement); | ||
} | ||
return nodes; | ||
} | ||
function getChangeType(prevEditorState, nextEditorState, dirtyLeavesSet, dirtyElementsSet, isComposing) { | ||
@@ -57,22 +49,17 @@ if (prevEditorState === null || dirtyLeavesSet.size === 0 && dirtyElementsSet.size === 0 && !isComposing) { | ||
} | ||
const nextSelection = nextEditorState._selection; | ||
const prevSelection = prevEditorState._selection; | ||
if (isComposing) { | ||
return COMPOSING_CHARACTER; | ||
} | ||
if (!lexical.$isRangeSelection(nextSelection) || !lexical.$isRangeSelection(prevSelection) || !prevSelection.isCollapsed() || !nextSelection.isCollapsed()) { | ||
return OTHER; | ||
} | ||
const dirtyNodes = getDirtyNodes(nextEditorState, dirtyLeavesSet, dirtyElementsSet); | ||
if (dirtyNodes.length === 0) { | ||
return OTHER; | ||
} // Catching the case when inserting new text node into an element (e.g. first char in paragraph/list), | ||
} | ||
// Catching the case when inserting new text node into an element (e.g. first char in paragraph/list), | ||
// or after existing node. | ||
if (dirtyNodes.length > 1) { | ||
@@ -82,71 +69,50 @@ const nextNodeMap = nextEditorState._nodeMap; | ||
const prevAnchorNode = nextNodeMap.get(prevSelection.anchor.key); | ||
if (nextAnchorNode && prevAnchorNode && !prevEditorState._nodeMap.has(nextAnchorNode.__key) && lexical.$isTextNode(nextAnchorNode) && nextAnchorNode.__text.length === 1 && nextSelection.anchor.offset === 1) { | ||
return INSERT_CHARACTER_AFTER_SELECTION; | ||
} | ||
return OTHER; | ||
} | ||
const nextDirtyNode = dirtyNodes[0]; | ||
const prevDirtyNode = prevEditorState._nodeMap.get(nextDirtyNode.__key); | ||
if (!lexical.$isTextNode(prevDirtyNode) || !lexical.$isTextNode(nextDirtyNode) || prevDirtyNode.__mode !== nextDirtyNode.__mode) { | ||
return OTHER; | ||
} | ||
const prevText = prevDirtyNode.__text; | ||
const nextText = nextDirtyNode.__text; | ||
if (prevText === nextText) { | ||
return OTHER; | ||
} | ||
const nextAnchor = nextSelection.anchor; | ||
const prevAnchor = prevSelection.anchor; | ||
if (nextAnchor.key !== prevAnchor.key || nextAnchor.type !== 'text') { | ||
return OTHER; | ||
} | ||
const nextAnchorOffset = nextAnchor.offset; | ||
const prevAnchorOffset = prevAnchor.offset; | ||
const textDiff = nextText.length - prevText.length; | ||
if (textDiff === 1 && prevAnchorOffset === nextAnchorOffset - 1) { | ||
return INSERT_CHARACTER_AFTER_SELECTION; | ||
} | ||
if (textDiff === -1 && prevAnchorOffset === nextAnchorOffset + 1) { | ||
return DELETE_CHARACTER_BEFORE_SELECTION; | ||
} | ||
if (textDiff === -1 && prevAnchorOffset === nextAnchorOffset) { | ||
return DELETE_CHARACTER_AFTER_SELECTION; | ||
} | ||
return OTHER; | ||
} | ||
function isTextNodeUnchanged(key, prevEditorState, nextEditorState) { | ||
const prevNode = prevEditorState._nodeMap.get(key); | ||
const nextNode = nextEditorState._nodeMap.get(key); | ||
const prevSelection = prevEditorState._selection; | ||
const nextSelection = nextEditorState._selection; | ||
let isDeletingLine = false; | ||
if (lexical.$isRangeSelection(prevSelection) && lexical.$isRangeSelection(nextSelection)) { | ||
isDeletingLine = prevSelection.anchor.type === 'element' && prevSelection.focus.type === 'element' && nextSelection.anchor.type === 'text' && nextSelection.focus.type === 'text'; | ||
} | ||
if (!isDeletingLine && lexical.$isTextNode(prevNode) && lexical.$isTextNode(nextNode)) { | ||
return prevNode.__type === nextNode.__type && prevNode.__text === nextNode.__text && prevNode.__mode === nextNode.__mode && prevNode.__detail === nextNode.__detail && prevNode.__style === nextNode.__style && prevNode.__format === nextNode.__format && prevNode.__parent === nextNode.__parent; | ||
} | ||
return false; | ||
} | ||
function createMergeActionGetter(editor, delay) { | ||
@@ -156,5 +122,6 @@ let prevChangeTime = Date.now(); | ||
return (prevEditorState, nextEditorState, currentHistoryEntry, dirtyLeaves, dirtyElements, tags) => { | ||
const changeTime = Date.now(); // If applying changes from history stack there's no need | ||
const changeTime = Date.now(); | ||
// If applying changes from history stack there's no need | ||
// to run history logic again, as history entries already calculated | ||
if (tags.has('historic')) { | ||
@@ -165,5 +132,3 @@ prevChangeType = OTHER; | ||
} | ||
const changeType = getChangeType(prevEditorState, nextEditorState, dirtyLeaves, dirtyElements, editor.isComposing()); | ||
const mergeAction = (() => { | ||
@@ -173,15 +138,11 @@ const isSameEditor = currentHistoryEntry === null || currentHistoryEntry.editor === editor; | ||
const shouldMergeHistory = !shouldPushHistory && isSameEditor && tags.has('history-merge'); | ||
if (shouldMergeHistory) { | ||
return HISTORY_MERGE; | ||
} | ||
if (prevEditorState === null) { | ||
return HISTORY_PUSH; | ||
} | ||
const selection = nextEditorState._selection; | ||
const prevSelection = prevEditorState._selection; | ||
const hasDirtyNodes = dirtyLeaves.size > 0 || dirtyElements.size > 0; | ||
if (!hasDirtyNodes) { | ||
@@ -191,15 +152,12 @@ if (prevSelection === null && selection !== null) { | ||
} | ||
return DISCARD_HISTORY_CANDIDATE; | ||
} | ||
if (shouldPushHistory === false && changeType !== OTHER && changeType === prevChangeType && changeTime < prevChangeTime + delay && isSameEditor) { | ||
return HISTORY_MERGE; | ||
} // A single node might have been marked as dirty, but not have changed | ||
} | ||
// A single node might have been marked as dirty, but not have changed | ||
// due to some node transform reverting the change. | ||
if (dirtyLeaves.size === 1) { | ||
const dirtyLeafKey = Array.from(dirtyLeaves)[0]; | ||
if (isTextNodeUnchanged(dirtyLeafKey, prevEditorState, nextEditorState)) { | ||
@@ -209,6 +167,4 @@ return HISTORY_MERGE; | ||
} | ||
return HISTORY_PUSH; | ||
})(); | ||
prevChangeTime = changeTime; | ||
@@ -219,10 +175,7 @@ prevChangeType = changeType; | ||
} | ||
function redo(editor, historyState) { | ||
const redoStack = historyState.redoStack; | ||
const undoStack = historyState.undoStack; | ||
if (redoStack.length !== 0) { | ||
const current = historyState.current; | ||
if (current !== null) { | ||
@@ -232,11 +185,7 @@ undoStack.push(current); | ||
} | ||
const historyStateEntry = redoStack.pop(); | ||
if (redoStack.length === 0) { | ||
editor.dispatchCommand(lexical.CAN_REDO_COMMAND, false); | ||
} | ||
historyState.current = historyStateEntry || null; | ||
if (historyStateEntry) { | ||
@@ -249,3 +198,2 @@ historyStateEntry.editor.setEditorState(historyStateEntry.editorState, { | ||
} | ||
function undo(editor, historyState) { | ||
@@ -255,7 +203,5 @@ const redoStack = historyState.redoStack; | ||
const undoStackLength = undoStack.length; | ||
if (undoStackLength !== 0) { | ||
const current = historyState.current; | ||
const historyStateEntry = undoStack.pop(); | ||
if (current !== null) { | ||
@@ -265,9 +211,6 @@ redoStack.push(current); | ||
} | ||
if (undoStack.length === 0) { | ||
editor.dispatchCommand(lexical.CAN_UNDO_COMMAND, false); | ||
} | ||
historyState.current = historyStateEntry || null; | ||
if (historyStateEntry) { | ||
@@ -280,3 +223,2 @@ historyStateEntry.editor.setEditorState(historyStateEntry.editorState.clone(historyStateEntry.undoSelection), { | ||
} | ||
function clearHistory(historyState) { | ||
@@ -287,6 +229,4 @@ historyState.undoStack = []; | ||
} | ||
function registerHistory(editor, historyState, delay) { | ||
const getMergeAction = createMergeActionGetter(editor, delay); | ||
const applyChange = ({ | ||
@@ -303,9 +243,6 @@ editorState, | ||
const currentEditorState = current === null ? null : current.editorState; | ||
if (current !== null && editorState === currentEditorState) { | ||
return; | ||
} | ||
const mergeAction = getMergeAction(prevEditorState, editorState, current, dirtyLeaves, dirtyElements, tags); | ||
if (mergeAction === HISTORY_PUSH) { | ||
@@ -315,5 +252,5 @@ if (redoStack.length !== 0) { | ||
} | ||
if (current !== null) { | ||
undoStack.push({ ...current, | ||
undoStack.push({ | ||
...current, | ||
undoSelection: prevEditorState.read(lexical.$getSelection) | ||
@@ -325,5 +262,5 @@ }); | ||
return; | ||
} // Else we merge | ||
} | ||
// Else we merge | ||
historyState.current = { | ||
@@ -334,3 +271,2 @@ editor, | ||
}; | ||
const unregisterCommandListener = utils.mergeRegister(editor.registerCommand(lexical.UNDO_COMMAND, () => { | ||
@@ -337,0 +273,0 @@ undo(editor, historyState); |
@@ -11,9 +11,9 @@ { | ||
"license": "MIT", | ||
"version": "0.7.8", | ||
"version": "0.7.9", | ||
"main": "LexicalHistory.js", | ||
"peerDependencies": { | ||
"lexical": "0.7.8" | ||
"lexical": "0.7.9" | ||
}, | ||
"dependencies": { | ||
"@lexical/utils": "0.7.8" | ||
"@lexical/utils": "0.7.9" | ||
}, | ||
@@ -20,0 +20,0 @@ "repository": { |
326
19102
+ Added@lexical/list@0.7.9(transitive)
+ Added@lexical/selection@0.7.9(transitive)
+ Added@lexical/table@0.7.9(transitive)
+ Added@lexical/utils@0.7.9(transitive)
+ Addedlexical@0.7.9(transitive)
- Removed@lexical/list@0.7.8(transitive)
- Removed@lexical/table@0.7.8(transitive)
- Removed@lexical/utils@0.7.8(transitive)
- Removedlexical@0.7.8(transitive)
Updated@lexical/utils@0.7.9