UNPKG

@syncfusion/ej2-documenteditor

Version:

Feature-rich document editor control with built-in support for context menu, options pane and dialogs.

958 lines (957 loc) 67.7 kB
import { isNullOrUndefined } from '@syncfusion/ej2-base'; import { ElementBox, ParagraphWidget, TableRowWidget, TableCellWidget, BookmarkElementBox, FootnoteElementBox, HeaderFooterWidget, ShapeElementBox } from '../viewer/page'; import { WCharacterFormat } from '../format/character-format'; import { WRowFormat } from '../format/row-format'; import { HelperMethods } from '../editor/editor-helper'; import { revisionActionEvent } from '../../base/index'; import { ChangesSingleView } from '../track-changes/track-changes-pane'; /** * The revision class which holds the information related to changes made in the document */ var Revision = /** @class */ (function () { function Revision(documentHelper, author, date, ownerNode) { /** * Gets or sets the author name who made the change */ this.author = null; /** * Indicates when the track changes made */ this.date = null; /** * To set the custom data value. */ this.customData = null; /** * @private */ this.revisionID = ''; /** * Used to update cursor position by ensuring items were removed or not */ this.isContentRemoved = false; this.isTableRevision = false; /** * Indicates whether to skip unlinking ranges for table elements. */ this.canSkipTableItems = false; this.skipUnLinkElement = false; /** * Private */ this.hasChanges = false; this.author = author; if (isNullOrUndefined(this.author)) { this.author = "Unknown"; } this.date = date; this.owner = documentHelper; this.ownerNode = ownerNode; } /** * Retrieves the content of the revision as an HTML string. * * @returns {string} The revision content as HTML string. */ Revision.prototype.getContent = function () { var content = ""; if (!isNullOrUndefined(this.owner.trackChangesPane.changes.get(this))) { var currentChangeView = this.owner.trackChangesPane.changes.get(this); if (!isNullOrUndefined(this.owner.revisions.groupedView.get(currentChangeView))) { var revisions = this.owner.revisions.groupedView.get(currentChangeView); var div = document.createElement('div'); var ranges = []; for (var i = 0; i < revisions.length; i++) { ranges = ranges.concat(revisions[i].getRange()); } currentChangeView.tableElement = undefined; currentChangeView.layoutElementText(this, ranges, div, true); content = div.innerHTML; } } return content; }; /** * Updates the date of the revisions shown in the track changes pane. * @param {string} value - The date to be set for the revision. * @returns {void} * Note: Revision dates are system-generated to preserve the audit trail and is strongly discouraged to modify it. * Calling this API permanently overwrites the original timestamp and cannot be recovered from the document history. This can undermine audit and compliance requirements. * Only use in controlled scenarios (e.g., data migration with approvals). For additional or custom timestamps, use the 'customData' property instead. */ Revision.prototype.setDate = function (value) { if (!isNullOrUndefined(value) && value != '') { var date = new Date(value); if (date.toString() !== 'Invalid Date') { // if the input is already in Utc format no need to convert to Utc. if (value.indexOf('Z') < 0) { this.date = HelperMethods.getUtcDate(date); } else { this.date = value; } this.owner.trackChangesPane.setDateInternal(this); } } }; /** * @private */ Revision.prototype.getRange = function (updateRange) { if (this.ownerNode instanceof ParagraphWidget) { if (isNullOrUndefined(this.range) || isNullOrUndefined(updateRange) || updateRange || this.hasChanges) { this.range = this.ownerNode.getRevisionRange(this); } return this.range; } else { return this.ownerNode.getRevisionRange(this); } }; /** * @private */ Revision.prototype.handleAcceptReject = function (isFromAccept, isGroupAcceptOrReject) { var start = this.owner.selection.start.clone(); var end = this.owner.selectionModule.end.clone(); this.owner.selectionModule.selectRevision(this, undefined, undefined, true); var selection = this.owner.selectionModule; var startPos = selection.start; var endPos = selection.end; if (!selection.start.isExistBefore(selection.end)) { startPos = selection.end; endPos = selection.start; } var blockInfo = selection.getParagraphInfo(startPos); var removeChanges = (!isNullOrUndefined(isFromAccept)) && ((this.revisionType === 'MoveFrom' || this.revisionType === 'Deletion') && isFromAccept) || ((this.revisionType === 'Insertion' || this.revisionType === 'MoveTo') && !isFromAccept); var comments; if (removeChanges) { var commentInfo = this.owner.editorModule.getSelectedComments(); if (commentInfo.commentEndInfo.length > 0 || commentInfo.commentStartInfo.length > 0) { comments = this.owner.editorModule.checkAndRemoveComments(false, true); } else { removeChanges = false; } } this.owner.editorModule.initHistory(isFromAccept ? 'Accept Change' : 'Reject Change'); var fieldBegin = selection.getHyperlinkField(); if (isFromAccept && this.revisionType === 'Deletion' && !isNullOrUndefined(fieldBegin) && this.getRange(false).indexOf(fieldBegin) !== -1 && this.getRange(false).indexOf(fieldBegin.fieldEnd) !== -1 && this.getRange(false).indexOf(fieldBegin.fieldSeparator) === this.getRange(false).indexOf(fieldBegin.fieldEnd) - 1) { this.owner.editorHistoryModule.currentBaseHistoryInfo.isHyperlinkField = true; } this.owner.editorHistoryModule.currentBaseHistoryInfo.markerData.push(this.owner.editorModule.getMarkerData(undefined, undefined, this)); if (this.revisionType === 'Deletion') { blockInfo = selection.getParagraphInfo(this.owner.selectionModule.start); selection.editPosition = this.owner.selectionModule.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString()); } else { selection.editPosition = this.owner.selectionModule.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString()); } this.owner.editorModule.updateInsertPosition(); this.isContentRemoved = false; this.canSkipTableItems = false; this.skipUnLinkElement = false; // Implement to accept/reject the revision if (this.revisionType === 'Insertion' || this.revisionType === 'Deletion' || this.revisionType === 'MoveFrom' || this.revisionType === 'MoveTo') { this.owner.isShiftingEnabled = true; var rangeIndex = 0; while (this.getRange().length > 0) { if (this.getRange()[rangeIndex] instanceof ElementBox || this.getRange()[rangeIndex] instanceof WCharacterFormat || this.getRange()[rangeIndex] instanceof WRowFormat) { if (this.getRange()[rangeIndex] instanceof BookmarkElementBox && isFromAccept && this.revisionType === 'Deletion') { var inline = this.getRange()[rangeIndex]; if (this.owner.documentHelper.bookmarks.containsKey(inline.name)) { this.owner.documentHelper.bookmarks.remove(inline.name); } } var moveToNextItem = this.unlinkRangeItem(this.getRange()[rangeIndex], this, isFromAccept, startPos, endPos); if (moveToNextItem) { rangeIndex++; } else { rangeIndex = 0; } } else { break; } } } this.isTableRevision = false; if (this.isContentRemoved) { var textPosition = selection.getTextPosBasedOnLogicalIndex(selection.editPosition); this.owner.selectionModule.selectContent(textPosition, true); this.owner.editorModule.updateEndPosition(); } else { selection.selectRange(startPos, endPos); this.owner.editorModule.updateHistoryPosition(endPos, false); if (!isNullOrUndefined(this.owner.editorHistory) && !isNullOrUndefined(this.owner.editorHistory.currentHistoryInfo) && (this.owner.editorHistory.currentHistoryInfo.action === 'Accept All' || this.owner.editorHistory.currentHistoryInfo.action === 'Reject All') && !blockInfo.paragraph.isInHeaderFooter) { this.owner.selection.selectPosition(start, end, true); this.owner.editorHistory.currentHistoryInfo.insertPosition = this.owner.selection.startOffset; this.owner.editorHistory.currentHistoryInfo.endPosition = this.owner.selection.endOffset; } } if (this.owner.editorHistoryModule && this.owner.editorHistoryModule.currentBaseHistoryInfo && this.owner.editorHistoryModule.currentBaseHistoryInfo.action !== 'BackSpace') { this.owner.editorHistoryModule.currentBaseHistoryInfo.removedNodes.reverse(); } if (this.owner.editorHistoryModule) { var editorHistory = this.owner.editorHistoryModule; if (editorHistory.currentHistoryInfo && (editorHistory.currentHistoryInfo.action === 'Accept All' || editorHistory.currentHistoryInfo.action === 'Reject All')) { if (this.owner.documentHelper.blockToShift) { this.owner.documentHelper.layout.shiftLayoutedItems(false); } } editorHistory.updateHistory(); if (removeChanges && this.owner.editorHistory && !isNullOrUndefined(this.owner.editorHistory.currentHistoryInfo)) { for (var k = 0; k < comments.length; k++) { // Reset the removedIds array of the current comment element to an empty array. if (comments[k].indexInOwner < 0) { comments[k].removedIds = []; this.owner.editorModule.initInsertInline(comments[k], false); } } this.owner.editorHistory.currentHistoryInfo.endPosition = this.owner.selection.startOffset; this.owner.editorHistory.updateComplexHistory(); } } if (!isGroupAcceptOrReject) { if (this.owner.selectionModule.start.paragraph.isInsideTable) { var table = this.owner.selectionModule.start.paragraph.containerWidget.ownerTable; this.owner.documentHelper.layout.reLayoutTable(table); } this.owner.editorModule.reLayout(this.owner.selectionModule); } if (blockInfo.paragraph.isInHeaderFooter) { this.owner.editorModule.updateHeaderFooterWidget(); } }; Revision.prototype.handleGroupAcceptReject = function (revision, isAccept) { var removeChanges = (!isNullOrUndefined(isAccept)) && ((this.revisionType === 'MoveFrom' || this.revisionType === 'Deletion') && isAccept) || ((this.revisionType === 'Insertion' || this.revisionType === 'MoveTo') && !isAccept); if (revision.length > 0) { if (!removeChanges) { var start = this.owner.selection.start.clone(); var end = this.owner.selectionModule.end.clone(); this.owner.editorModule.initComplexHistory(isAccept ? 'Accept All' : 'Reject All'); this.owner.selectionModule.selectRevision(this); this.owner.selection.isModifyingSelectionInternally = true; while (revision.length > 0) { if (isAccept) { revision[revision.length - 1].handleAcceptReject(true, true); } else { revision[revision.length - 1].handleAcceptReject(false, true); } } if (this.owner.selectionModule.start.paragraph.isInsideTable) { var table = this.owner.selectionModule.start.paragraph.containerWidget.ownerTable; this.owner.documentHelper.layout.reLayoutTable(table); } this.owner.selection.isModifyingSelectionInternally = false; this.owner.selection.selectPosition(start, end, true); if (!isNullOrUndefined(this.owner.editorHistory) && !isNullOrUndefined(this.owner.editorHistory.currentHistoryInfo) && (this.owner.editorHistory.currentHistoryInfo.action === 'Accept All' || this.owner.editorHistory.currentHistoryInfo.action === 'Reject All')) { this.owner.editorHistory.currentHistoryInfo.insertPosition = this.owner.selection.startOffset; this.owner.editorHistory.currentHistoryInfo.endPosition = this.owner.selection.endOffset; } if (this.owner.editorHistoryModule) { this.owner.editorHistoryModule.updateComplexHistory(); } } else { this.deleteTrackedContents(isAccept); } } }; Revision.prototype.deleteTrackedContents = function (isAccept) { //The boolean was used to check that if the revision from the item was was already removed or not. var isItemAlreadyUnlinked = this.owner.selectionModule.selectRevision(this, undefined, undefined, undefined, true, isAccept); if (!isItemAlreadyUnlinked) { this.owner.editorModule.initHistory(isAccept ? 'Accept Change' : 'Reject Change'); this.owner.editorModule.deleteSelectedContents(this.owner.selectionModule, true); if (!isNullOrUndefined(this.owner.editorHistory) && this.owner.editorHistoryModule.currentBaseHistoryInfo) { this.owner.editorHistoryModule.currentBaseHistoryInfo.isAcceptOrReject = isAccept ? 'Accept' : 'Reject'; } if (!isNullOrUndefined(this.owner.editorHistory) && !isNullOrUndefined(this.owner.editorHistory.currentHistoryInfo) && (this.owner.editorHistory.currentHistoryInfo.action === 'Accept All' || this.owner.editorHistory.currentHistoryInfo.action === 'Reject All')) { this.owner.editorHistory.currentHistoryInfo.insertPosition = this.owner.selection.startOffset; this.owner.editorHistory.currentHistoryInfo.endPosition = this.owner.selection.endOffset; } this.owner.editorModule.reLayout(this.owner.selectionModule, undefined, undefined, true); } }; /** * Method which accepts the selected revision, revision marks will be removed and changes will be included in the viewer. * * @returns {void} */ Revision.prototype.accept = function () { var eventArgs = { author: this.author, cancel: false, revisionType: this.revisionType, actionType: 'Accept', source: this }; this.owner.trigger(revisionActionEvent, eventArgs); if (eventArgs.cancel) { return; } var handled = false; if (!this.owner.documentHelper.isTrackedOnlyMode) { var revisions = []; if (!isNullOrUndefined(this.owner.trackChangesPane.changes.get(this))) { revisions = this.owner.revisions.groupedView.get(this.owner.trackChangesPane.changes.get(this)); } if (revisions.length > 1) { this.handleGroupAcceptReject(revisions, true); handled = true; } if (!handled) { this.handleAcceptReject(true, false); } } }; /** * Method which rejects the selected revision, revision marks will be removed leaving the original content. */ Revision.prototype.reject = function () { var eventArgs = { author: this.author, cancel: false, revisionType: this.revisionType, actionType: 'Reject', source: this }; this.owner.trigger(revisionActionEvent, eventArgs); if (eventArgs.cancel) { return; } var handled = false; if (!this.owner.documentHelper.isTrackedOnlyMode) { var revisions = []; if (!isNullOrUndefined(this.owner.trackChangesPane.changes.get(this))) { revisions = this.owner.revisions.groupedView.get(this.owner.trackChangesPane.changes.get(this)); } if (revisions.length > 1) { this.handleGroupAcceptReject(revisions, false); handled = true; } if (!handled) { this.handleAcceptReject(false, false); } } }; /** * Select the current revision. */ Revision.prototype.select = function () { this.owner.selectionModule.selectRevision(this); }; /** * Unlinks revision and its assosiated range * @private * @param item * @param revision * @param isFromAccept */ /* eslint-disable */ Revision.prototype.unlinkRangeItem = function (item, revision, isFromAccept, start, end) { if (this.isTableRevision) { this.removeCurrentRevisionFromItem(item); if (revision.getRange().length === 0) { this.owner.revisions.remove(revision); } return false; } var removeChanges = (!isNullOrUndefined(isFromAccept)) && ((revision.revisionType === 'MoveFrom' || revision.revisionType === 'Deletion') && isFromAccept) || ((revision.revisionType === 'Insertion' || revision.revisionType === 'MoveTo') && !isFromAccept); if (this.owner.selectionModule.isTOC()) { if (removeChanges) { this.owner.editorModule.deleteSelectedContents(this.owner.selectionModule, true); if (revision.getRange().length === 0) { this.owner.revisions.remove(revision); } this.isContentRemoved = true; this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'BackSpace'; } else { while (this.getRange().length > 0) { var currentElement = this.getRange()[0]; this.removeCurrentRevisionFromItem(currentElement); if (revision.getRange().length === 0) { this.owner.revisions.remove(revision); } } this.owner.editorModule.addRemovedNodes(this.revisionID); this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'ClearRevisions'; } return false; } if (item instanceof ElementBox && !this.canSkipTableItems) { if (removeChanges) { if (!this.skipeElementRemoval(item)) { this.owner.editorModule.addRemovedNodes(item.clone()); } else { this.skipUnLinkElement = true; return true; } } else { // Bug 873011: Handled the hyperlink formatting preservation when rejecting the RemoveHyperlink action. var fieldBegin = this.owner.selectionModule.getHyperlinkField(); if (!isFromAccept && !isNullOrUndefined(fieldBegin) && fieldBegin == item && !isNullOrUndefined(fieldBegin.fieldEnd)) { this.owner.editorModule.initComplexHistory('ClearRevisions'); this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'ClearRevisions'; this.updateRevisionID(); this.removeRevisionFromPara(start, end); if (!isNullOrUndefined(this.owner.editorHistoryModule)) { this.owner.editorHistoryModule.currentBaseHistoryInfo.isHyperlinkField = true; var endInfo = this.owner.selectionModule.getParagraphInfo(end); var endIndex = this.owner.selectionModule.getHierarchicalIndex(endInfo.paragraph, endInfo.offset.toString()); this.owner.editorHistoryModule.currentBaseHistoryInfo.endPosition = endIndex; this.owner.editorHistoryModule.currentBaseHistoryInfo.selectionEnd = endIndex; this.owner.editorHistoryModule.updateHistory(); } if (this.owner.enableTrackChanges) { this.owner.enableTrackChanges = false; this.owner.editorModule.updateHyperlinkFormat(this.owner.selectionModule); this.owner.enableTrackChanges = true; } else { this.owner.editorModule.updateHyperlinkFormat(this.owner.selectionModule); } if (this.owner.editorHistoryModule && !isNullOrUndefined(this.owner.editorHistoryModule.currentHistoryInfo)) { this.owner.editorHistoryModule.updateComplexHistory(); } } else { this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'ClearRevisions'; this.updateRevisionID(); this.removeRevisionFromPara(start, end); } } } else if (!this.canSkipTableItems && (item instanceof WCharacterFormat) && (!removeChanges)) { this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'ClearRevisions'; this.updateRevisionID(); this.removeRevisionFromPara(start, end); } else if (item instanceof WRowFormat && !removeChanges) { this.isTableRevision = true; var tableWidget = item.ownerBase.ownerTable; var currentRow = item.ownerBase; this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'RemoveRowTrack'; if (this.owner.enableCollaborativeEditing) { this.owner.editorHistoryModule.currentBaseHistoryInfo.createAcceptRejectRowOperation('RemoveRowTrack', currentRow); } this.owner.editorModule.cloneTableToHistoryInfo(tableWidget.combineWidget(this.owner.viewer)); } removeChanges = removeChanges && !this.canSkipTableItems; if (item instanceof ElementBox && removeChanges) { var currentPara = item.line.paragraph; this.removeAllRevisionsFromItem(item); if (item instanceof FootnoteElementBox) { if (item.footnoteType === 'Footnote') { this.owner.editorModule.removeFootnote(item); } else { this.owner.editorModule.removeEndnote(item); } } else if (item instanceof ShapeElementBox) { this.owner.editorModule.removeDeletedShapeRevision(item); } this.removeItem(item); this.isContentRemoved = true; var skipRelayout = !isNullOrUndefined(currentPara) && !isNullOrUndefined(currentPara.bodyWidget) && currentPara.bodyWidget instanceof HeaderFooterWidget && (isNullOrUndefined(currentPara.bodyWidget.page) || (!isNullOrUndefined(currentPara.bodyWidget.page) && currentPara.bodyWidget.page.index === -1)); if (!skipRelayout) { this.owner.documentHelper.layout.reLayoutParagraph(currentPara, 0, 0); } if (isNullOrUndefined(currentPara.childWidgets)) { var textPosition = this.owner.selectionModule.getTextPosBasedOnLogicalIndex(this.owner.selectionModule.editPosition); this.owner.selectionModule.selectContent(textPosition, true); } } else if (item instanceof WCharacterFormat && removeChanges) { this.isContentRemoved = true; this.skipUnLinkElement = false; this.owner.editor.addRemovedRevisionInfo(item); this.removeAllRevisionsFromItem(item); if (revision.getRange().length === 1) { this.owner.editorModule.deleteSelectedContents(this.owner.selectionModule, true); } else { this.owner.editorModule.deleteSelectedContents(this.owner.selectionModule, true); this.removeRevisionFromPara(start, end); var rangeIndex = revision.getRange().indexOf(item); if (rangeIndex >= 0) { revision.getRange().splice(rangeIndex, 1); } this.owner.trackChangesPane.updateCurrentTrackChanges(revision); while (this.getRange().length > 0) { this.removeCurrentRevisionFromItem(this.getRange()[0]); } } this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'BackSpace'; this.owner.editorHistoryModule.currentBaseHistoryInfo.isAcceptOrReject = isFromAccept ? 'Accept' : 'Reject'; } else if (item instanceof WRowFormat && removeChanges) { var tableWidget = item.ownerBase.ownerTable; tableWidget = tableWidget.combineWidget(this.owner.viewer); var currentRow = item.ownerBase; this.owner.editor.addRemovedRevisionInfo(item); this.removeAllRevisionsFromItem(item); this.owner.editorHistoryModule.currentBaseHistoryInfo.action = 'DeleteCells'; this.owner.editorHistoryModule.currentBaseHistoryInfo.isAcceptOrReject = isFromAccept ? 'Accept' : 'Reject'; this.owner.editorModule.cloneTableToHistoryInfo(tableWidget); this.owner.editorModule.removeRevisionsInRow(currentRow); this.isContentRemoved = true; tableWidget.removeChild(tableWidget.childWidgets.indexOf(currentRow)); this.canSkipTableItems = true; // Before destroying the table row widget, delete the field element from the row. this.owner.editorModule.removeFieldInBlock(currentRow); // Before destroying the table row widget, delete the bookmark element from the row. this.owner.editorModule.removeFieldInBlock(currentRow, true); // Before destroying the table row widget, delete the content control element from the row. this.owner.editorModule.removeFieldInBlock(currentRow, undefined, true); //currentRow.destroy(); if (tableWidget.childWidgets.length === 0) { this.owner.selectionModule.editPosition = this.owner.selectionModule.getHierarchicalIndex(tableWidget, '0'); this.owner.editorModule.removeBlock(tableWidget); //tableWidget.destroy(); } else { this.owner.editorModule.updateTable(tableWidget, true); } } // if the range is of row format, we will remove the row and for history preservation we use whole table to be cloned, hence skipping this part if (!(item instanceof WRowFormat) || !removeChanges) { if (!this.skipUnLinkElement) { this.removeCurrentRevisionFromItem(item); if (removeChanges && item instanceof BookmarkElementBox) { this.owner.editorModule.removedBookmarkElements.push(item); } if (item instanceof BookmarkElementBox) { if (this.owner.documentHelper.bookmarks.containsKey(item.name)) { if (this.owner.enableCollaborativeEditing && !isNullOrUndefined(this.owner.editorHistory.currentBaseHistoryInfo)) { this.owner.editorHistory.currentBaseHistoryInfo.markerData.push({ bookmarkName: item.name }); } this.owner.documentHelper.bookmarks.remove(item.name); } } } } if (revision.getRange().length === 0) { this.owner.revisions.remove(revision); } return false; }; Revision.prototype.removeRevisionFromPara = function (start, end) { var blockInfo = this.owner.selectionModule.getParagraphInfo(start); var endBlockInfo = this.owner.selectionModule.getParagraphInfo(end); var para = blockInfo.paragraph; while (para instanceof ParagraphWidget) { if (para.characterFormat.revisionLength > 0) { for (var i = 0; i < para.characterFormat.revisionLength; i++) { if (para.characterFormat.getRevision(i).getRange().length === 0) { var revisionIndex = para.characterFormat.getAllRevision().indexOf(para.characterFormat.getRevision(i)); para.characterFormat.removeRevision(revisionIndex); i--; } } } if (endBlockInfo.paragraph === para) { para = undefined; } else { para = para.nextWidget; } } }; Revision.prototype.updateRevisionID = function () { this.owner.editorModule.addRemovedNodes(this.revisionID); while (this.getRange().length > 0) { this.removeCurrentRevisionFromItem(this.getRange()[0], true); } this.owner.trackChangesPane.updateCurrentTrackChanges(this); }; /* eslint-disable @typescript-eslint/no-explicit-any */ Revision.prototype.removeAllRevisionsFromItem = function (item) { if (item.revisions.length > 0) { for (var i = item.revisionLength - 1; i >= 0; i--) { var currentRevision = item.revisions[i]; // let rangeIndex: number = currentRevision.getRange().indexOf(item); // item.revisions[revisionIndex].getRange().splice(rangeIndex, 1); item.removeRevision(item.getAllRevision().indexOf(currentRevision)); this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); // Added condition to removed the another revision from collection which is present in the item. The current revision will be removed at the end of the unlinkRangeItem method. if (this.revisionID !== currentRevision.revisionID) { if (currentRevision.getRange().length === 0) { this.owner.revisions.remove(currentRevision); } } } } }; /** * Method to remove current revision from the item * * @private * @param {any} item - Specifies the item * @returns {void} */ /* eslint-disable @typescript-eslint/no-explicit-any */ Revision.prototype.removeCurrentRevisionFromItem = function (item, skipUpdate) { var revisionIndex = item.getAllRevision().indexOf(this); if (revisionIndex >= 0) { item.removeRevision(revisionIndex); if (!skipUpdate) { this.owner.trackChangesPane.updateCurrentTrackChanges(this); } } }; /** * @private * @param {Element} element - Specifies the element. * @returns {boolean} Resturs skip element removal */ Revision.prototype.skipeElementRemoval = function (element) { var elementPara = element.paragraph; if (elementPara.characterFormat.revisionLength > 0) { for (var i = 0; i < elementPara.characterFormat.revisionLength; i++) { var currentRevision = elementPara.characterFormat.getRevision(i); var rangeIndex = currentRevision.getRange().indexOf(element); if (rangeIndex >= 0 && currentRevision.revisionID === this.revisionID) { return true; } } } return false; }; Revision.prototype.removeItem = function (element) { var paraWidget = element.line.paragraph; this.owner.editorModule.unLinkFieldCharacter(element); this.owner.editorModule.triggerChangeDetected(element); var elementIndex = element.line.children.indexOf(element); var previousNode = element.previousNode; element.line.children.splice(elementIndex, 1); if (!isNullOrUndefined(previousNode)) { this.owner.editorModule.combineElementRevisionToPrevNxt(previousNode); } var paraFloatingElementIndex = element.line.paragraph.floatingElements.indexOf(element); element.line.paragraph.floatingElements.splice(paraFloatingElementIndex, 1); var blockFloatingElementIndex = element.line.paragraph.bodyWidget.floatingElements.indexOf(element); if (blockFloatingElementIndex > -1) { element.line.paragraph.bodyWidget.floatingElements.splice(blockFloatingElementIndex, 1); } this.owner.editorModule.removeEmptyLine(paraWidget); }; Revision.prototype.canSkipCloning = function () { if (!isNullOrUndefined(this.owner) && this.owner.editorHistoryModule && this.owner.editorHistoryModule.currentBaseHistoryInfo) { var baseHistoryInfo = this.owner.editorHistoryModule.currentBaseHistoryInfo; if (baseHistoryInfo.action === 'DeleteCells') { return true; } } return false; }; /** * @private * */ Revision.prototype.destroy = function () { this.author = undefined; this.revisionType = undefined; this.revisionID = undefined; this.date = undefined; this.range = []; this.range = undefined; this.owner = undefined; this.ownerNode = undefined; this.customData = undefined; }; /** * @private * @returns {Revision} - Returns revision */ Revision.prototype.clone = function () { if (this.canSkipCloning()) { return this; } var revision = new Revision(undefined, this.author, this.date); revision.revisionID = this.revisionID; revision.revisionType = this.revisionType; revision.customData = this.customData; return revision; }; /** * @private */ Revision.prototype.cloneRevision = function () { var revision = new Revision(this.owner, this.author, this.date); revision.revisionID = this.revisionID; revision.revisionType = this.revisionType; revision.author = this.author; revision.date = this.date; revision.customData = this.customData; return revision; }; /** * Method to clone the revisions for the element * * @param {Revision[]} revisions - revision array. * @returns {string[]} - returns clones revisions. */ Revision.cloneRevisions = function (revisions) { var clonedRevisions = []; for (var i = 0; i < revisions.length; i++) { clonedRevisions.push(revisions[i].revisionID); } return clonedRevisions; }; return Revision; }()); export { Revision }; /** * Represents the revision collections in the document. */ var RevisionCollection = /** @class */ (function () { function RevisionCollection(owner) { /** * @private */ this.revisions = []; /** * @private */ this.changes = []; /** * @private */ this.isAcceptAllOrRejectAll = false; this.owner = owner; } /** * @private */ RevisionCollection.prototype.get = function (index) { if (index >= this.revisions.length || index < 0) { throw new ReferenceError('Provided index is not within the range'); } return this.revisions[index]; }; Object.defineProperty(RevisionCollection.prototype, "length", { get: function () { return this.revisions.length; }, enumerable: true, configurable: true }); /** * @private */ RevisionCollection.prototype.checkAndGetPreviousRevisionToCombine = function (revision) { var range = revision.getRange(); var revisionToCombine; if (range.length > 0) { var firstElement = range[0]; if (firstElement instanceof ElementBox) { var previousElement = this.owner.editor.getPreviousNodeRevision(firstElement.previousNode); var currentParagraph = firstElement.paragraph.getSplitWidgets()[0]; var skipAuthorCheck = currentParagraph.containerWidget instanceof TableCellWidget && currentParagraph.containerWidget.ownerRow.rowFormat.revisionLength > 0; var previousBlock = currentParagraph.previousRenderedWidget; var commonRevision = []; if ((previousElement instanceof ElementBox && previousElement.revisionLength > 0 && this.isSameRevisionType(previousElement.getAllRevision(), revision, commonRevision, skipAuthorCheck)) || (isNullOrUndefined(previousElement) && previousBlock instanceof ParagraphWidget && previousBlock.characterFormat.revisionLength > 0 && this.isSameRevisionType(previousBlock.characterFormat.getAllRevision(), revision, commonRevision, skipAuthorCheck))) { if (commonRevision.length > 0) { revisionToCombine = commonRevision[0]; } } } else if (firstElement instanceof WCharacterFormat) { var block = firstElement.ownerBase; var splittedParagraph = block.getSplitWidgets(); var skipAuthorCheck = splittedParagraph[splittedParagraph.length - 1].containerWidget instanceof TableCellWidget && splittedParagraph[splittedParagraph.length - 1].containerWidget.ownerRow.rowFormat.revisionLength > 0; var previousBlock = splittedParagraph[0].previousRenderedWidget; var previousElement = void 0; var commonRevision = []; if (block.isEmpty() && previousBlock instanceof ParagraphWidget) { previousElement = previousBlock.characterFormat; } else { var lastLine = splittedParagraph[splittedParagraph.length - 1].lastChild; previousElement = this.owner.editor.getPreviousNodeRevision(lastLine.children[lastLine.children.length - 1]); if (isNullOrUndefined(previousElement) && previousBlock instanceof ParagraphWidget) { previousElement = previousBlock.characterFormat; } } if (!isNullOrUndefined(previousElement) && previousElement.revisionLength > 0 && this.isSameRevisionType(previousElement.getAllRevision(), revision, commonRevision, skipAuthorCheck)) { if (commonRevision.length > 0) { revisionToCombine = commonRevision[0]; } } } else if (firstElement instanceof WRowFormat) { var rowWidget = firstElement.ownerBase; var skipAuthorCheck = rowWidget.ownerTable.containerWidget instanceof TableCellWidget && rowWidget.ownerTable.containerWidget.ownerRow.rowFormat.revisionLength > 0; var previousRow = rowWidget.previousRenderedWidget; var commonRevision = []; if (!isNullOrUndefined(previousRow) && previousRow.rowFormat.revisionLength > 0 && this.isSameRevisionType(previousRow.rowFormat.getAllRevision(), revision, commonRevision, skipAuthorCheck)) { if (commonRevision.length > 0) { revisionToCombine = commonRevision[0]; } } } if (isNullOrUndefined(revisionToCombine)) { var block = void 0; if (firstElement instanceof ElementBox) { block = firstElement.paragraph; } else if (firstElement instanceof WCharacterFormat) { block = firstElement.ownerBase; } else if (firstElement instanceof WRowFormat) { block = firstElement.ownerBase.ownerTable; } var container = block.containerWidget; if (container instanceof TableCellWidget) { var rowFormat = container.ownerRow.rowFormat; var commonRevision = []; if (rowFormat.revisionLength > 0 && this.isSameRevisionType(rowFormat.getAllRevision(), revision, commonRevision, true)) { revisionToCombine = commonRevision[0]; } } } } return revisionToCombine; }; /** * @private */ RevisionCollection.prototype.checkAndGetNextRevisionToCombine = function (revision) { var range = revision.getRange(); if (range.length > 0) { var firstElement = range[0]; var lastElement = range[range.length - 1]; if (firstElement instanceof ElementBox) { var nextNode = lastElement.nextNode; var currentParagraph = firstElement.paragraph.getSplitWidgets()[0]; var skipAuthorCheck = currentParagraph.containerWidget instanceof TableCellWidget && currentParagraph.containerWidget.ownerRow.rowFormat.revisionLength > 0; var commonRevision = []; if ((nextNode instanceof ElementBox && nextNode.revisionLength > 0 && this.isSameRevisionType(nextNode.getAllRevision(), revision, commonRevision, skipAuthorCheck)) || (isNullOrUndefined(nextNode) && currentParagraph.characterFormat.revisionLength > 0 && this.isSameRevisionType(currentParagraph.characterFormat.getAllRevision(), revision, commonRevision, skipAuthorCheck))) { if (commonRevision.length > 0) { return commonRevision[0]; } } } else if (firstElement instanceof WCharacterFormat) { var block = firstElement.ownerBase; var splittedParagraph = block.getSplitWidgets(); var skipAuthorCheck = splittedParagraph[splittedParagraph.length - 1].containerWidget instanceof TableCellWidget && splittedParagraph[splittedParagraph.length - 1].containerWidget.ownerRow.rowFormat.revisionLength > 0; var nextBlock = splittedParagraph[splittedParagraph.length - 1].nextRenderedWidget; var nextElement = void 0; if (nextBlock instanceof ParagraphWidget) { if (nextBlock.isEmpty()) { nextElement = nextBlock.characterFormat; } else { nextElement = this.owner.editor.getNextNodeRevision(nextBlock.firstChild.children[0]); if (isNullOrUndefined(nextElement) && nextBlock instanceof ParagraphWidget) { nextElement = nextBlock.characterFormat; } } } var commonRevision = []; if (!isNullOrUndefined(nextElement) && nextElement.revisionLength > 0 && this.isSameRevisionType(nextElement.getAllRevision(), revision, commonRevision, skipAuthorCheck)) { return commonRevision[0]; } } else if (firstElement instanceof WRowFormat) { var rowWidget = firstElement.ownerBase; var skipAuthorCheck = rowWidget.ownerTable.containerWidget instanceof TableCellWidget && rowWidget.ownerTable.containerWidget.ownerRow.rowFormat.revisionLength > 0; var nextRow = rowWidget.nextRenderedWidget; var commonRevision = []; if (!isNullOrUndefined(nextRow) && nextRow.rowFormat.revisionLength > 0 && this.isSameRevisionType(nextRow.rowFormat.getAllRevision(), revision, commonRevision, skipAuthorCheck)) { if (commonRevision.length > 0) { return commonRevision[0]; } } } } return undefined; }; /** * @private */ RevisionCollection.prototype.addRevision = function (revision) { this.insertRevisionAt(this.changes.length, revision); }; /** * @private */ RevisionCollection.prototype.insertRevisionAt = function (index, revision) { var previousRevision = this.checkAndGetPreviousRevisionToCombine(revision); var nextRevision = this.checkAndGetNextRevisionToCombine(revision); if (previousRevision) { this.combineWithExistingRevision(index, revision, previousRevision, false); if (nextRevision) { this.combineWithNextRevision(revision, nextRevision); } } else if (nextRevision && !isNullOrUndefined(this.owner.trackChangesPane.changes.get(nextRevision))) { this.combineWithExistingRevision(index, revision, nextRevision, true); } else { this.insertNewRevision(index, revision); } this.changes.splice(index, 0, revision); }; RevisionCollection.prototype.getIndexToInsertInGroup = function (revisions, revisionToCombine, currentRevision, index) { // if the previous row has a revision, It will return the row revision index not the child blocks. In that case we need to calculate the index based on the child blocks. if (revisionToCombine.ownerNode instanceof WRowFormat) { //Get previous revision to get the index to insert in grouped revision. var previousRevision = this.changes[index - 1]; if (previousRevision === revisionToCombine) { return revisions.indexOf(revisionToCombine) + (this.changes.indexOf(revisionToCombine) < index ? 1 : 0); } else { if (revisions.indexOf(previousRevision) !== -1) { return revisions.indexOf(previousRevision) + (this.changes.indexOf(previousRevision) < index ? 1 : 0); } else { return revisions.indexOf(revisionToCombine) + (this.changes.indexOf(revisionToCombine) < index ? 1 : 0); } } } else { return revisions.indexOf(revisionToCombine) + (this.changes.indexOf(revisionToCombine) < index ? 1 : 0); } }; RevisionCollection.prototype.combineWithExistingRevision = function (index, revision, revisionToCombine, nextRevision) { var currentChangeView = this.owner.trackChangesPane.changes.get(revisionToCombine); if (!currentChangeView) { return; } var revisions = this.owner.revisions.groupedView.get(currentChangeView); var insertIndex = this.getIndexToInsertInGroup(revisions, revisionToCombine, revision, index); revisions.splice(insertIndex, 0, revision); this.owner.trackChangesPane.changes.add(revision, currentChangeView); // When deleting the content it will be deleted in the reverse order. so that we need to update the owner node. If it is next node we need to update the revision because of owner node. if (nextRevision) { var revisionIndex = this.owner.revisions.revisions.indexOf(revisionToCombine); if (revisionIndex != -1) { this.owner.revisions.revisions.splice(revisionIndex, 1, revision); currentChangeView.revision = revision; } } if (revision.getRange().length > 0) { if (!isNullOrUndefined(currentChangeView.singleInnerDiv)) { this.clearChildren(currentChangeView.singleInnerDiv.querySelector("#textDiv")); } var ranges = []; for (var i = 0; i < revisions.length; i++) { ranges = ranges.concat(revisions[i].getRange()); } currentChangeView.layoutElementText(revision, ranges, !isNullOrUndefined(currentChangeView.singleInnerDiv) ? currentChangeView.singleInnerDiv.querySelector("#textDiv") : undefined); } }; RevisionCollection.prototype.clearChildren = function (element) { while (element.firstChild) { element.removeChild(element.firstChild); } }; RevisionCollection.prototype.getNextRevision = function (index, previousRevision) { // If two revisions are present in the element there is possible of change in revision type. So that view will not be split. In this case, we need to check all the revision which are present in the element. // Retrun the revision are match to the previous revision. If not then it will return the next revision directly. var nextRevision = this.changes[index]; if (nextRevision && previousRevision) {