677 lines
19 KiB
JavaScript
677 lines
19 KiB
JavaScript
/*
|
|
* (c) Copyright Ascensio System SIA 2010-2024
|
|
*
|
|
* This program is a free software product. You can redistribute it and/or
|
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
* version 3 as published by the Free Software Foundation. In accordance with
|
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
* of any third-party rights.
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
*
|
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
|
* street, Riga, Latvia, EU, LV-1050.
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions
|
|
* of the Program must display Appropriate Legal Notices, as required under
|
|
* Section 5 of the GNU AGPL version 3.
|
|
*
|
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
* grant you any rights under trademark law for use of our trademarks.
|
|
*
|
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
* well as technical writing content are licensed under the terms of the
|
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
*
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
(function ()
|
|
{
|
|
/**
|
|
* Класс, восстанавливающий удаленные части документа
|
|
* @param {AscWord.Document} logicDocument
|
|
* @constructor
|
|
*/
|
|
function DeletedTextRecovery(logicDocument)
|
|
{
|
|
this.document = logicDocument;
|
|
|
|
/**
|
|
* Список всех изменений связанных с удалением текста
|
|
* @type {*[]}
|
|
*/
|
|
this.m_RewiewDelPoints = [];
|
|
this.arrColor = [];
|
|
|
|
this.userId = undefined;
|
|
this.userName = undefined;
|
|
this.userTime = undefined;
|
|
}
|
|
/**
|
|
* Восстанавливаем удаленный текст в текущей точке истории версий
|
|
* @return {boolean}
|
|
*/
|
|
DeletedTextRecovery.prototype.RecoverDeletedText = function()
|
|
{
|
|
this.UndoRecoveredText();
|
|
return this.ShowDelText();
|
|
};
|
|
/**
|
|
* Отменяем восстановление удаленного текста, если оно было
|
|
*/
|
|
DeletedTextRecovery.prototype.UndoRecoveredText = function ()
|
|
{
|
|
if (!this.HaveRecoveredText())
|
|
return;
|
|
|
|
let localHistory = AscCommon.History;
|
|
let changes = localHistory.Undo();
|
|
this.document.UpdateAfterUndoRedo(changes);
|
|
localHistory.ClearRedo();
|
|
};
|
|
/**
|
|
* Запрашивем,есть ли восстановленный удаленный текст
|
|
* @return {boolean}
|
|
*/
|
|
DeletedTextRecovery.prototype.HaveRecoveredText = function()
|
|
{
|
|
let localHistory = AscCommon.History;
|
|
let lastPoint = localHistory.Points[localHistory.Points.length - 1];
|
|
return !!(lastPoint && lastPoint.Description === AscDFH.historydescription_Collaborative_DeletedTextRecovery);
|
|
};
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Private area
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* Инициализация и создание промежуточных данных для отображения удаленного текста в текущей ревизии
|
|
*/
|
|
DeletedTextRecovery.prototype.HandleChanges = function()
|
|
{
|
|
AscCommon.CollaborativeEditing.CoHistory.SplitChangesByPoints();
|
|
|
|
let oCoHistory = AscCommon.CollaborativeEditing.CoHistory;
|
|
let arrChangesList = oCoHistory.Changes;
|
|
let arrPointsList = AscCommon.CollaborativeEditing.CoHistory.ChangesSplitByPoints;
|
|
let nIndex = AscCommon.CollaborativeEditing.CoHistory.curChangeIndex;
|
|
let arrChanges = arrChangesList.slice(0, arrPointsList[nIndex]);
|
|
|
|
if (!arrChanges || !arrChanges.length)
|
|
return;
|
|
|
|
this.m_RewiewDelPoints = arrChanges;
|
|
};
|
|
/**
|
|
* Получаем подготовленные данные, разбитые по точкам
|
|
* @return {*[]}
|
|
*/
|
|
DeletedTextRecovery.prototype.GetChanges = function()
|
|
{
|
|
let arr = this.m_RewiewDelPoints.slice();
|
|
|
|
let arrOutput = []
|
|
for (let i = 0; i < arr.length; i++)
|
|
{
|
|
let oChange = arr[i];
|
|
if (oChange.ConvertToSimpleChanges)
|
|
{
|
|
let arrSplitChange = oChange.ConvertToSimpleChanges();
|
|
if (arrSplitChange && arrSplitChange.length)
|
|
{
|
|
for (let j = 0; j < arrSplitChange.length; j++)
|
|
{
|
|
arrOutput.push(arrSplitChange[j])
|
|
}
|
|
} else
|
|
{
|
|
arrOutput.push(oChange);
|
|
}
|
|
}
|
|
else
|
|
arrOutput.push(oChange);
|
|
|
|
}
|
|
return arrOutput;
|
|
};
|
|
DeletedTextRecovery.prototype.GetRemoveTextChanges = function (arrInputChanges, oRemoveText)
|
|
{
|
|
let oAddText = new AddTextPositions();
|
|
|
|
// отбираем удаленный текст связанный с текущей ревизией
|
|
for (let i = 0; i < arrInputChanges.length; i++)
|
|
{
|
|
let oCurChange = arrInputChanges[i];
|
|
|
|
// пропускаем все изменения связанные со сплитом
|
|
if (oCurChange instanceof CChangesRunOnStartSplit)
|
|
{
|
|
while (oCurChange && !(oCurChange instanceof CChangesRunOnEndSplit))
|
|
{
|
|
i++;
|
|
oCurChange = arrInputChanges[i];
|
|
}
|
|
}
|
|
|
|
if (oCurChange === undefined)
|
|
break;
|
|
|
|
if (oCurChange instanceof AscCommon.CChangesTableIdDescription || !oCurChange.Copy)
|
|
continue;
|
|
|
|
let oNewCurChange = oCurChange.Copy();
|
|
|
|
oRemoveText.ProceedChange(oNewCurChange);
|
|
|
|
if (oNewCurChange instanceof CChangesRunAddItem || oNewCurChange instanceof CChangesParagraphAddItem || oNewCurChange instanceof CChangesDocumentAddItem)
|
|
oAddText.Add(oCurChange.Class, oCurChange, oCurChange.UseArray ? oCurChange.PosArray[0] : oCurChange.Pos, i);
|
|
else if (oNewCurChange instanceof CChangesRunRemoveItem || oNewCurChange instanceof CChangesParagraphRemoveItem || oNewCurChange instanceof CChangesDocumentRemoveItem)
|
|
oRemoveText.Check(oAddText, oCurChange, i);
|
|
}
|
|
oRemoveText.DelDuplicate();
|
|
}
|
|
DeletedTextRecovery.prototype.CommuteChanges = function (arrInputChanges, arrSaveData, oRemoveText)
|
|
{
|
|
// коммутируем изменения
|
|
let arrRevInput = arrInputChanges;
|
|
|
|
let arrDelChangesForCommute = oRemoveText.GetArrayChanges();
|
|
|
|
for (let j = 0; j < arrDelChangesForCommute.length; j++)
|
|
{
|
|
let oCurItem = arrDelChangesForCommute[j];
|
|
let nPos = oCurItem.nIndex;
|
|
let oChange = oCurItem.item;
|
|
|
|
if (oChange.IsContentChange())
|
|
{
|
|
let _oChange = oChange.Copy();
|
|
|
|
if (AscCommon.CollaborativeEditing.CoHistory.CommuteContentChange(_oChange, nPos, arrRevInput))
|
|
arrSaveData.push(_oChange);
|
|
}
|
|
else
|
|
{
|
|
arrSaveData.push(oChange);
|
|
}
|
|
}
|
|
|
|
oRemoveText.ResetData();
|
|
}
|
|
/**
|
|
* Отменяем заданные изменения
|
|
* @param arrInputChanges
|
|
* @return {*[]}
|
|
*/
|
|
DeletedTextRecovery.prototype.RedoUndoChanges = function (arrInputChanges)
|
|
{
|
|
let oRemoveText = new RemoveTextPositions();
|
|
let arrChanges = [];
|
|
let arrDelChanges = [];
|
|
|
|
this.GetRemoveTextChanges(arrInputChanges, oRemoveText);
|
|
this.CommuteChanges(arrInputChanges, arrDelChanges, oRemoveText);
|
|
|
|
for (let i = 0; i < arrDelChanges.length; i++)
|
|
{
|
|
this.RedoUndoChange(arrDelChanges[i], false, arrChanges);
|
|
let nPos = arrDelChanges[i].UseArray
|
|
? arrDelChanges[i].PosArray[0]
|
|
: arrDelChanges[i].Pos;
|
|
|
|
oRemoveText.Add(
|
|
arrDelChanges[i].Class,
|
|
arrDelChanges[i],
|
|
nPos,
|
|
i
|
|
);
|
|
}
|
|
|
|
let result = {
|
|
data: oRemoveText.ProceedPositions(this),
|
|
classes: oRemoveText.oClasses
|
|
};
|
|
|
|
return [arrChanges, result];
|
|
};
|
|
DeletedTextRecovery.prototype.ShowDelText = function ()
|
|
{
|
|
let versionHistory = this.document.GetApi().getVersionHistory();
|
|
if (!versionHistory)
|
|
return false;
|
|
|
|
this.HandleChanges();
|
|
let arrInput = this.GetChanges();
|
|
if (arrInput.length === 0)
|
|
return false;
|
|
|
|
let localHistory = AscCommon.History;
|
|
localHistory.Create_NewPoint(AscDFH.historydescription_Collaborative_DeletedTextRecovery);
|
|
|
|
this.userId = versionHistory.userId;
|
|
this.userName = versionHistory.userName;
|
|
this.userTime = new Date(versionHistory.dateOfRevision).getTime();
|
|
|
|
// отменяем изменения до нужного места (необходимо для перемещения по истории)
|
|
let arrCurrentPoint = this.RedoUndoChanges(arrInput);
|
|
let delChanges = arrCurrentPoint[0];
|
|
let arrResult = arrCurrentPoint[1];
|
|
|
|
for (let i = 0; i < delChanges.length; i++)
|
|
{
|
|
this.document.History.Add(delChanges[i]);
|
|
}
|
|
this.Split(arrResult);
|
|
this.document.RecalculateByChanges(delChanges);
|
|
|
|
this.m_RewiewDelPoints = [];
|
|
return true;
|
|
};
|
|
DeletedTextRecovery.prototype.Split = function (arrInput)
|
|
{
|
|
let data = arrInput.data;
|
|
let classes = arrInput.classes;
|
|
let arrKeys = Object.keys(data);
|
|
|
|
for (let nKey = 0; nKey < arrKeys.length; nKey++)
|
|
{
|
|
let strCurrentKey = arrKeys[nKey];
|
|
let arrCurrentRunData = data[strCurrentKey];
|
|
let oCurrentRun = classes[strCurrentKey];
|
|
|
|
arrCurrentRunData.sort(function (a, b) { return a.nStart - b.nStart });
|
|
|
|
for (let j = arrCurrentRunData.length - 1; j >= 0; j--)
|
|
{
|
|
let oCurrentRule = arrCurrentRunData[j];
|
|
let nStart = oCurrentRule.nStart;
|
|
let nEnd = oCurrentRule.nEnd;
|
|
|
|
if (oCurrentRun instanceof CDocument)
|
|
{
|
|
let arrContent = oCurrentRun.Content;
|
|
|
|
for (let j = nStart; j <= nEnd; j++)
|
|
{
|
|
let oCurrentParagraph = arrContent[j];
|
|
if (oCurrentParagraph)
|
|
this.SetReviewInfo(oCurrentParagraph);
|
|
}
|
|
}
|
|
else if (oCurrentRun instanceof Paragraph)
|
|
{
|
|
let arrContent = oCurrentRun.Content;
|
|
|
|
if (nStart === 0 && arrContent.length === nEnd)
|
|
{
|
|
this.SetReviewInfo(oCurrentRun);
|
|
}
|
|
else
|
|
{
|
|
for (let i = nStart; i <= nEnd; i++)
|
|
{
|
|
this.SetReviewInfo(arrContent[i]);
|
|
}
|
|
}
|
|
}
|
|
else if (oCurrentRun instanceof ParaRun)
|
|
{
|
|
let newCollab = [];
|
|
|
|
if (oCurrentRun.Content.length === 0 || (nEnd + 1 - nStart) === oCurrentRun.Content.length)
|
|
{
|
|
this.SetReviewInfo(oCurrentRun);
|
|
continue;
|
|
}
|
|
|
|
for (let i = 0; i < oCurrentRun.CollaborativeMarks.Ranges.length; i++)
|
|
{
|
|
let oCollab = oCurrentRun.CollaborativeMarks.Ranges[i];
|
|
newCollab.push({PosS: oCollab.PosS, PosE: oCollab.PosE, Color: oCollab.Color, oCurrentRun: oCurrentRun});
|
|
}
|
|
|
|
let oParent = oCurrentRun.GetParent();
|
|
let RunPos = this.FindPosInParent(oCurrentRun);
|
|
let RightRun = oCurrentRun.SplitForSpreadCollaborativeMark(nStart);
|
|
|
|
oParent.Add_ToContent(RunPos + 1, RightRun);
|
|
let oNewer = RightRun.SplitForSpreadCollaborativeMark(nEnd - nStart + 1);
|
|
|
|
oParent.Add_ToContent(RunPos + 2, oNewer);
|
|
this.SetReviewInfo(RightRun);
|
|
|
|
for (let i = 0; i < newCollab.length; i++)
|
|
{
|
|
let oCurCollaborativeMark = newCollab[i];
|
|
this.arrColor.push(oCurCollaborativeMark);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DeletedTextRecovery.prototype.SetReviewInfo = function (oReviewInfoParent)
|
|
{
|
|
if (!oReviewInfoParent === undefined)
|
|
return;
|
|
|
|
// TODO: Проверку по каким классам нужно проходить лучше переделать
|
|
if (!oReviewInfoParent || !oReviewInfoParent.GetReviewInfo)
|
|
{
|
|
if (oReviewInfoParent instanceof ParaMath)
|
|
{
|
|
let oRootContent = oReviewInfoParent.Root.Content;
|
|
for (let i = 0; i < oRootContent.length; i++)
|
|
{
|
|
let oCurrentContent = oRootContent[i];
|
|
this.SetReviewInfo(oCurrentContent);
|
|
}
|
|
}
|
|
else if (oReviewInfoParent.Content.length > 0)
|
|
{
|
|
for (let i = 0; i < oReviewInfoParent.Content.length; i++)
|
|
{
|
|
let oCurrentContent = oReviewInfoParent.Content[i];
|
|
this.SetReviewInfo(oCurrentContent);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (oReviewInfoParent.GetReviewType() !== reviewtype_Remove)
|
|
{
|
|
let reviewInfo = oReviewInfoParent.GetReviewInfo();
|
|
if (!reviewInfo)
|
|
reviewInfo = new AscWord.ReviewInfo();
|
|
else
|
|
reviewInfo = reviewInfo.Copy();
|
|
|
|
reviewInfo.UserId = this.userId;
|
|
reviewInfo.UserName = this.userName;
|
|
reviewInfo.DateTime = this.userTime;
|
|
|
|
oReviewInfoParent.SetReviewTypeWithInfo(reviewtype_Remove, reviewInfo, false);
|
|
}
|
|
};
|
|
DeletedTextRecovery.prototype.FindPosInParent = function(oClass)
|
|
{
|
|
let oParent = oClass.GetParent();
|
|
let arrParentContent = oParent.Content;
|
|
|
|
for (let i = 0; i < arrParentContent.length; i++)
|
|
{
|
|
if (arrParentContent[i] === oClass)
|
|
return i;
|
|
}
|
|
};
|
|
DeletedTextRecovery.prototype.RedoUndoChange = function (oChange, isRedo, arrToSave)
|
|
{
|
|
if (!oChange)
|
|
return;
|
|
|
|
if (oChange.IsContentChange())
|
|
{
|
|
let arrSimpleChanges = oChange.ConvertToSimpleChanges();
|
|
|
|
for (let simpleIndex = arrSimpleChanges.length - 1; simpleIndex >= 0; simpleIndex--)
|
|
{
|
|
if (isRedo)
|
|
arrSimpleChanges[simpleIndex].Redo();
|
|
else
|
|
arrSimpleChanges[simpleIndex].Undo();
|
|
|
|
|
|
let oRevChange = arrSimpleChanges[simpleIndex];
|
|
|
|
if (!isRedo)
|
|
oRevChange = oRevChange.CreateReverseChange();
|
|
|
|
if (oRevChange)
|
|
arrToSave.push(oRevChange);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isRedo)
|
|
oChange.Redo();
|
|
else
|
|
oChange.Undo();
|
|
|
|
let oRevChange = oChange;
|
|
|
|
if (!isRedo)
|
|
oRevChange = oRevChange.CreateReverseChange();
|
|
|
|
if (oRevChange)
|
|
arrToSave.push(oRevChange);
|
|
}
|
|
};
|
|
|
|
function AddTextPositions()
|
|
{
|
|
this.data = {};
|
|
|
|
this.Add = function (oClass, oItem, Pos, nIndex)
|
|
{
|
|
if (!this.data[oClass.Id])
|
|
this.data[oClass.Id] = [];
|
|
|
|
this.data[oClass.Id].push({item: oItem, pos: Pos, nIndex: nIndex});
|
|
}
|
|
}
|
|
function RemoveTextPositions()
|
|
{
|
|
this.data = {};
|
|
this.oClasses = {};
|
|
this.arrClasses = [];
|
|
|
|
this.Check = function (oAddText, oCurChange, i)
|
|
{
|
|
if (oCurChange.Class)
|
|
{
|
|
let strCurrentId = oCurChange.Class.Id;
|
|
let arrRemData = oAddText.data[strCurrentId];
|
|
|
|
if (!arrRemData)
|
|
{
|
|
this.Add(oCurChange.Class, oCurChange, oCurChange.UseArray ? oCurChange.PosArray[0] : oCurChange.Pos, i);
|
|
return;
|
|
}
|
|
|
|
let addItem = oCurChange.Items[0];
|
|
|
|
for (let i = 0; i < arrRemData.length; i++)
|
|
{
|
|
let oCurrentRemItem = arrRemData[i];
|
|
|
|
if (oCurChange.UseArray && oCurChange.PosArray[0] === oCurrentRemItem.pos && addItem.Value === oCurrentRemItem.item.Items[0].Value)
|
|
{
|
|
return false;
|
|
}
|
|
else if (!oCurChange.UseArray && oCurChange.Pos === oCurrentRemItem.pos && addItem.Value === oCurrentRemItem.item.Items[0].Value)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.Add(oCurChange.Class, oCurChange, oCurChange.UseArray ? oCurChange.PosArray[0] : oCurChange.Pos, i);
|
|
}
|
|
this.DelDuplicate = function ()
|
|
{
|
|
let arrKeys = Object.keys(this.data);
|
|
|
|
for (let nKey = 0; nKey < arrKeys.length; nKey++)
|
|
{
|
|
let strCurrentKey = arrKeys[nKey];
|
|
let arrCurrentRunData = this.data[strCurrentKey];
|
|
|
|
for (let i = 0; i < arrCurrentRunData.length; i++)
|
|
{
|
|
for (let j = i + 1; j < arrCurrentRunData.length; j++)
|
|
{
|
|
if (arrCurrentRunData[i].item === arrCurrentRunData[j].item)
|
|
{
|
|
arrCurrentRunData.splice(j, 1);
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.Add = function (oClass, oItem, Pos, nIndex)
|
|
{
|
|
if (!this.data[oClass.Id])
|
|
this.data[oClass.Id] = [];
|
|
|
|
this.data[oClass.Id].push({item: oItem, pos: Pos, nIndex: nIndex});
|
|
}
|
|
this.GetArrayChanges = function ()
|
|
{
|
|
let arrOutput = []
|
|
let arrKeys = Object.keys(this.data);
|
|
|
|
for (let nKey = 0; nKey < arrKeys.length; nKey++)
|
|
{
|
|
let strCurrentKey = arrKeys[nKey];
|
|
let arrCurrentRunData = this.data[strCurrentKey];
|
|
|
|
for (let i = 0; i < arrCurrentRunData.length; i++)
|
|
{
|
|
arrOutput.push(arrCurrentRunData[i]);
|
|
}
|
|
}
|
|
return arrOutput;
|
|
}
|
|
this.ProceedChange = function (oChange)
|
|
{
|
|
if (oChange.Class && !this.oClasses[oChange.Class.Id])
|
|
{
|
|
this.oClasses[oChange.Class.Id] = oChange.Class;
|
|
if (-1 === this.arrClasses.indexOf(oChange.Class.Id))
|
|
{
|
|
this.arrClasses.push(oChange.Class.Id);
|
|
}
|
|
}
|
|
}
|
|
this.FindInParent = function (oClass, oItem)
|
|
{
|
|
let arrParentContent = oClass.Content;
|
|
|
|
for (let nPos = 0; nPos < arrParentContent.length; nPos++)
|
|
{
|
|
if (arrParentContent[nPos] === oItem)
|
|
return nPos;
|
|
}
|
|
}
|
|
this.ProceedPositions = function ()
|
|
{
|
|
for (let nKey = 0; nKey < this.arrClasses.length; nKey++)
|
|
{
|
|
let strCurrentKey = this.arrClasses[nKey];
|
|
let arrCurrentRunData = this.data[strCurrentKey];
|
|
if (!arrCurrentRunData)
|
|
continue;
|
|
let oClass = this.oClasses[strCurrentKey];
|
|
let newArrCurrentRunData = [];
|
|
|
|
for (let i = 0; i < arrCurrentRunData.length; i++)
|
|
{
|
|
let oItem = arrCurrentRunData[i];
|
|
|
|
let nPos = this.FindInParent(oClass, oItem.item.Items[0]);
|
|
newArrCurrentRunData.push(nPos);
|
|
}
|
|
|
|
let nCurrentPos;
|
|
let nPrevPos;
|
|
let nTempPrevPos;
|
|
|
|
for (let nPos = 1; nPos < newArrCurrentRunData.length; nPos++)
|
|
{
|
|
nPrevPos = newArrCurrentRunData[nPos - 1];
|
|
nCurrentPos = newArrCurrentRunData[nPos];
|
|
|
|
if (nTempPrevPos === nCurrentPos || nCurrentPos === nPrevPos)
|
|
{
|
|
if (nTempPrevPos)
|
|
{
|
|
nTempPrevPos = undefined;
|
|
newArrCurrentRunData[nPos] = nPrevPos + 1;
|
|
nTempPrevPos = nCurrentPos;
|
|
}
|
|
else
|
|
{
|
|
newArrCurrentRunData[nPos] = nCurrentPos + 1;
|
|
nTempPrevPos = nCurrentPos;
|
|
}
|
|
}
|
|
}
|
|
this.data[strCurrentKey] = newArrCurrentRunData;
|
|
}
|
|
let transformedObject = CollapsePositions(this.data);
|
|
return transformedObject
|
|
}
|
|
this.ResetData = function ()
|
|
{
|
|
this.data = {};
|
|
}
|
|
}
|
|
function CollapsePositions (oInput)
|
|
{
|
|
let transformedObject = {};
|
|
for (let key in oInput)
|
|
{
|
|
if (oInput.hasOwnProperty(key))
|
|
{
|
|
let values = oInput[key];
|
|
let pairs = [];
|
|
let nStart = null;
|
|
let nEnd = null;
|
|
let decreasingSequence = false;
|
|
|
|
for (let i = 0; i < values.length; i++)
|
|
{
|
|
let value = values[i];
|
|
|
|
if (nStart === null)
|
|
{
|
|
nStart = value;
|
|
nEnd = value;
|
|
}
|
|
else if (value === nEnd + 1)
|
|
{
|
|
nEnd = value;
|
|
decreasingSequence = false;
|
|
}
|
|
else if (value === nEnd - 1)
|
|
{
|
|
nStart = value;
|
|
decreasingSequence = true;
|
|
}
|
|
else
|
|
{
|
|
pairs.push({ nStart : nStart, nEnd: nEnd });
|
|
nStart = value;
|
|
nEnd = value;
|
|
decreasingSequence = false;
|
|
}
|
|
}
|
|
|
|
if (nStart !== null && nEnd !== null)
|
|
pairs.push({ nStart : nStart, nEnd: nEnd });
|
|
|
|
transformedObject[key] = pairs;
|
|
}
|
|
}
|
|
return transformedObject;
|
|
}
|
|
//--------------------------------------------------------export----------------------------------------------------
|
|
AscCommon.DeletedTextRecovery = DeletedTextRecovery;
|
|
|
|
})();
|