UNPKG

@syncfusion/ej2-documenteditor

Version:

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

1,059 lines 66.8 kB
/* eslint-disable */ import { TextPosition, TextSearchResults } from '../index'; import { beforeXmlHttpRequestSend } from './../../index'; import { Dictionary } from '../../base/dictionary'; import { TextElementBox, ErrorTextElementBox, TableCellWidget, FieldElementBox } from '../viewer/page'; import { isNullOrUndefined } from '@syncfusion/ej2-base'; /** * The spell checker module */ var SpellChecker = /** @class */ (function () { function SpellChecker(documentHelper) { this.langIDInternal = 0; /** * Specifies whether spell check has to be performed or not. */ this.enableSpellCheckInternal = true; /** * @private */ /* eslint-disable @typescript-eslint/no-explicit-any */ this.uniqueSpelledWords = {}; /** * Every time rendering text elementbox we are checking the key length of the uniqueSpelledWords object. This causes performance issue So optimizing it. */ this.uniqueSpelledWordsCount = 0; this.spellSuggestionInternal = true; /** * @private */ this.uniqueKey = ''; this.removeUnderlineInternal = false; this.combinedElements = []; /** * @default 1000 */ this.uniqueWordsCountInternal = 15000; this.performOptimizedCheck = true; /** * @private */ this.isChangeAll = false; this.documentHelper = documentHelper; this.errorWordCollection = new Dictionary(); this.uniqueWordsCollection = new Dictionary(); this.errorSuggestions = new Dictionary(); this.ignoreAllItems = []; this.uniqueSpelledWords = {}; if (!isNullOrUndefined(this.documentHelper)) { this.textSearchResults = new TextSearchResults(this.documentHelper.owner); this.uniqueKey = this.documentHelper.owner.element.id + '_' + this.createGuid(); } } /** * Gets module name. */ SpellChecker.prototype.getModuleName = function () { return 'SpellChecker'; }; Object.defineProperty(SpellChecker.prototype, "enableOptimizedSpellCheck", { /** * Gets the boolean indicating whether optimized spell check to be performed. * * @aspType bool * @returns {boolean} Returns enableOptimizedSpellCheck */ get: function () { return this.performOptimizedCheck; }, /** * Sets the boolean indicating whether optimized spell check to be performed. * * @aspType bool */ set: function (value) { this.performOptimizedCheck = value; }, enumerable: true, configurable: true }); Object.defineProperty(SpellChecker.prototype, "uniqueWordsCount", { /** * Gets the spell checked Unique words. * * @aspType int */ get: function () { return isNullOrUndefined(this.uniqueWordsCountInternal) ? 0 : this.uniqueWordsCountInternal; }, /** * Sets the spell checked Unique words. * * @aspType int */ set: function (value) { this.uniqueWordsCountInternal = value; }, enumerable: true, configurable: true }); Object.defineProperty(SpellChecker.prototype, "languageID", { /** * Gets the languageID. * * @aspType int */ get: function () { return isNullOrUndefined(this.langIDInternal) ? 0 : this.langIDInternal; }, /** * Sets the languageID. * * @aspType int */ set: function (value) { this.langIDInternal = value; }, enumerable: true, configurable: true }); Object.defineProperty(SpellChecker.prototype, "allowSpellCheckAndSuggestion", { /** * Getter indicates whether suggestion enabled. * * @aspType bool */ get: function () { return this.spellSuggestionInternal; }, /** * Setter to enable or disable suggestion * * @aspType bool */ set: function (value) { this.spellSuggestionInternal = value; }, enumerable: true, configurable: true }); Object.defineProperty(SpellChecker.prototype, "removeUnderline", { /** * Getter indicates whether underline removed for mis-spelled word. * * @aspType bool */ get: function () { return this.removeUnderlineInternal; }, /** * Setter to enable or disable underline for mis-spelled word * * @aspType bool */ set: function (value) { this.removeUnderlineInternal = value; this.documentHelper.owner.editorModule.reLayout(this.documentHelper.selection); }, enumerable: true, configurable: true }); Object.defineProperty(SpellChecker.prototype, "enableSpellCheck", { /** * Getter indicates whether spell check has to be performed or not. * * @aspType bool */ get: function () { return this.enableSpellCheckInternal; }, /** * Setter to enable or disable spell check has to be performed or not * * @aspType bool */ set: function (value) { this.enableSpellCheckInternal = value; this.documentHelper.owner.editorModule.reLayout(this.documentHelper.selection); }, enumerable: true, configurable: true }); Object.defineProperty(SpellChecker.prototype, "viewer", { get: function () { return this.documentHelper.owner.viewer; }, enumerable: true, configurable: true }); /** * Method to manage replace logic * * @private */ SpellChecker.prototype.manageReplace = function (content, dialogElement) { this.documentHelper.triggerSpellCheck = true; var exactText = ''; var elementInfo; if (!isNullOrUndefined(dialogElement) && dialogElement instanceof ErrorTextElementBox) { var exactText_1 = dialogElement.text; this.documentHelper.selection.start = dialogElement.start.clone(); this.documentHelper.selection.end = dialogElement.end.clone(); if (content !== 'Ignore Once') { content = this.manageSpecialCharacters(exactText_1, content); this.documentHelper.owner.editorModule.insertTextInternal(content, true); this.documentHelper.selection.start.setPositionInternal(this.documentHelper.selection.end); this.documentHelper.clearSelectionHighlight(); return; } else { this.currentContextInfo = { 'text': exactText_1, 'element': dialogElement }; } } if (!isNullOrUndefined(this.currentContextInfo) && this.currentContextInfo.element && content !== 'Ignore Once') { var elementBox = this.currentContextInfo.element; exactText = this.currentContextInfo.element.text; this.documentHelper.selection.start = elementBox.start.clone(); this.documentHelper.selection.end = elementBox.end.clone(); } else { this.handleReplace(content); } if (content !== 'Ignore Once') { this.documentHelper.owner.editorModule.insertTextInternal(content, true); if (!isNullOrUndefined(this.currentContextInfo)) { this.removeErrorsFromCollection(this.currentContextInfo); } this.documentHelper.selection.start.setPositionInternal(this.documentHelper.selection.end); this.documentHelper.clearSelectionHighlight(); } //this.documentHelper.owner.errorWordCollection.remove(content); this.documentHelper.triggerSpellCheck = false; }; /** * Method to handle replace logic * * @private */ SpellChecker.prototype.handleReplace = function (content) { var startPosition = this.documentHelper.selection.start; var offset = startPosition.offset; var startIndex = 0; var startInlineObj = startPosition.currentWidget.getInline(offset, startIndex, false, true); var startOffset = startInlineObj.element.line.getOffset(startInlineObj.element, 0) + startInlineObj.element.length; if (startOffset === offset) { this.retrieveExactElementInfo(startInlineObj); } var exactText = startInlineObj.element.text; var startPattern = new RegExp('^[#\\@\\!\\~\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\'\\,\\<\\.\\>\\/\\?\\`\\s]+', 'g'); var matches = []; var matchInfo; // eslint-disable no-cond-assign while (!isNullOrUndefined(matchInfo = startPattern.exec(exactText))) { matches.push(matchInfo); } if (content === 'Ignore Once') { this.handleIgnoreOnce(startInlineObj); return; } startPosition.offset = offset - startInlineObj.index; if (!isNullOrUndefined(matches) && matches.length > 0) { startPosition.offset += matches[0].toString().length; } startPosition.location = this.documentHelper.owner.selectionModule.getPhysicalPositionInternal(startPosition.currentWidget, startPosition.offset, true); startPosition = this.documentHelper.owner.searchModule.textSearch.getTextPosition(startPosition.currentWidget, startPosition.offset.toString()); //startPosition.location = this.owner.selection.getPhysicalPositionInternal(span.line, offset, true); startPosition.setPositionParagraph(startPosition.currentWidget, startPosition.offset); var index = (startPosition.offset + startInlineObj.element.length) - startPosition.offset; var endOffset = startPosition.currentWidget.getOffset(startInlineObj.element, index); var lineWidget = startPosition.currentWidget; var endPattern = new RegExp('[#\\@\\!\\~\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\'\\,\\<\\.\\>\\/\\?\\s\\`]+$', 'g'); matches = []; // eslint-disable no-cond-assign while (!isNullOrUndefined(matchInfo = endPattern.exec(exactText))) { matches.push(matchInfo); } if (!isNullOrUndefined(matches) && matches.length > 0) { endOffset -= matches[0].toString().length; } this.documentHelper.selection.end = this.documentHelper.owner.searchModule.textSearch.getTextPosition(lineWidget, endOffset.toString()); this.documentHelper.selection.end.location = this.documentHelper.owner.selectionModule.getPhysicalPositionInternal(startPosition.currentWidget, endOffset, true); this.documentHelper.selection.end.setPositionParagraph(lineWidget, endOffset); this.currentContextInfo = { 'element': startInlineObj.element, 'text': startInlineObj.element.text }; }; /** * Method to retrieve exact element info * * @private */ SpellChecker.prototype.retrieveExactElementInfo = function (startInlineObj) { var nextElement = startInlineObj.element.nextElement; if (!isNullOrUndefined(nextElement) && nextElement instanceof TextElementBox) { var nextTextElBox = nextElement; if (nextTextElBox.text.trim() != "") { startInlineObj.element = nextElement; } } }; /** * Method to handle to ignore error Once * * @private */ SpellChecker.prototype.handleIgnoreOnce = function (startInlineObj) { var textElement = startInlineObj.element; if (!isNullOrUndefined(this.currentContextInfo) && this.currentContextInfo.element && this.currentContextInfo.element instanceof ErrorTextElementBox) { var errorElement = this.currentContextInfo.element; var startPosition = errorElement.start; var endPosition = errorElement.end; var startInlineObj_1 = startPosition.currentWidget.getInline(startPosition.offset, 0, false, true).element; var endInlineObj = endPosition.currentWidget.getInline(endPosition.offset, 0, false, true).element; while (true) { var exactText = this.manageSpecialCharacters(errorElement.text, undefined, true); if (startInlineObj_1.ignoreOnceItems.indexOf(exactText) === -1) { startInlineObj_1.ignoreOnceItems.push(exactText); } if (startInlineObj_1 === endInlineObj) { break; } startInlineObj_1 = startInlineObj_1.nextNode; } } else { var exactText = this.manageSpecialCharacters(textElement.text, undefined, true); if (textElement.ignoreOnceItems.indexOf(exactText) === -1) { textElement.ignoreOnceItems.push(exactText); } } this.documentHelper.owner.editorModule.reLayout(this.documentHelper.selection); }; /** * Method to handle ignore all items * * @private */ SpellChecker.prototype.handleIgnoreAllItems = function (contextElement) { var contextItem = (!isNullOrUndefined(contextElement)) ? contextElement : this.retriveText(); var retrievedText = this.manageSpecialCharacters(contextItem.text, undefined, true); if (this.ignoreAllItems.indexOf(retrievedText) === -1) { this.ignoreAllItems.push(retrievedText); this.removeErrorsFromCollection(contextItem); this.documentHelper.triggerSpellCheck = true; this.documentHelper.owner.editorModule.reLayout(this.documentHelper.selection); this.documentHelper.triggerSpellCheck = false; this.documentHelper.clearSelectionHighlight(); } }; /** * Method to handle dictionary * * @private */ SpellChecker.prototype.handleAddToDictionary = function (contextElement) { var _this = this; var contextItem = (!isNullOrUndefined(contextElement)) ? contextElement : this.retriveText(); var retrievedText = this.manageSpecialCharacters(contextItem.text, undefined, true); /* eslint-disable @typescript-eslint/no-explicit-any */ this.callSpellChecker(this.languageID, retrievedText, false, false, true).then(function (data) { if (!isNullOrUndefined(_this.documentHelper)) { _this.documentHelper.triggerSpellCheck = true; _this.removeErrorsFromCollection(contextItem); _this.ignoreAllItems.push(retrievedText); _this.documentHelper.owner.editorModule.reLayout(_this.documentHelper.selection, true); _this.documentHelper.triggerSpellCheck = false; } }); }; /** * Method to append/remove special characters * * @private */ SpellChecker.prototype.manageSpecialCharacters = function (exactText, replaceText, isRemove) { if (!isNullOrUndefined(exactText)) { var isRemoveSpecChar = false; if (isNullOrUndefined(replaceText)) { isRemoveSpecChar = true; replaceText = exactText; } var pattern = new RegExp('^[#\\@\\!\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\\”\'\\,\\<\\.\\>\\/\\?\\`\\s\\’]+', 'g'); var matches = []; var matchInfo = void 0; // eslint-disable no-cond-assign while (!isNullOrUndefined(matchInfo = pattern.exec(exactText))) { matches.push(matchInfo); } if (matches.length > 0) { for (var i = 0; i < matches.length; i++) { /* eslint-disable @typescript-eslint/no-explicit-any */ var match = matches[i]; replaceText = (!isRemove) ? match[0] + replaceText : replaceText.replace(match[0], ''); } } var endPattern = new RegExp('[#\\@\\!\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\\”\'\\,\\<\\.\\>\\/\\?\\s\\`\\’]+$', 'g'); matches = []; var originalText = replaceText; if (!isRemove) { originalText = exactText; } // eslint-disable no-cond-assign while (!isNullOrUndefined(matchInfo = endPattern.exec(originalText))) { matches.push(matchInfo); } if (matches.length > 0) { for (var i = 0; i < matches.length; i++) { /* eslint-disable @typescript-eslint/no-explicit-any */ var match = matches[i]; replaceText = (!isRemove) ? replaceText + match[0] : replaceText.slice(0, match.index); } } // if the text contains zero width characters, remove them. var zeroWidthPattern = /[\u200B-\u200D\uFEFF]/g; replaceText = replaceText.replace(zeroWidthPattern, ''); } return replaceText; }; /** * Method to remove errors * * @private */ SpellChecker.prototype.removeErrorsFromCollection = function (contextItem) { if (!isNullOrUndefined(contextItem.text) && this.errorWordCollection.containsKey(contextItem.text)) { var textElement = this.errorWordCollection.get(contextItem.text); if (textElement.indexOf(contextItem.element) >= 0) { textElement.splice(0, 1); } if (textElement.length === 0) { this.errorWordCollection.remove(contextItem.text); } } }; /** * Method to retrieve exact text * * @private */ SpellChecker.prototype.retriveText = function () { var exactText; var currentElement; if (!isNullOrUndefined(this.currentContextInfo) && this.currentContextInfo.element) { currentElement = this.currentContextInfo.element; exactText = this.currentContextInfo.element.text; this.documentHelper.selection.start = currentElement.start.clone(); this.documentHelper.selection.end = currentElement.end.clone(); } else { var startPosition = this.documentHelper.selection.start; var offset = startPosition.offset; var startIndex = 0; var startInlineObj = startPosition.currentWidget.getInline(offset, startIndex); currentElement = startInlineObj.element; exactText = startInlineObj.element.text; } return { 'text': exactText, 'element': currentElement }; }; /** * Method to handle suggestions * * @private */ /* eslint-disable @typescript-eslint/no-explicit-any */ SpellChecker.prototype.handleSuggestions = function (allsuggestions) { this.spellCheckSuggestion = []; if (allsuggestions.length === 0) { this.spellCheckSuggestion.push(this.documentHelper.owner.contextMenuModule.locale.getConstant('Add to Dictionary')); } else { allsuggestions = (allsuggestions.length > 3) ? this.constructInlineMenu(allsuggestions) : allsuggestions; this.spellCheckSuggestion.push(this.documentHelper.owner.contextMenuModule.locale.getConstant('Add to Dictionary')); } /* eslint-disable @typescript-eslint/no-explicit-any */ var spellSuggestion = []; if (this.spellCheckSuggestion.length > 0) { for (var _i = 0, _a = this.spellCheckSuggestion; _i < _a.length; _i++) { var str = _a[_i]; spellSuggestion.push({ text: str, id: this.documentHelper.owner.element.id + '_contextmenu_otherSuggestions_spellcheck_' + (str === this.documentHelper.owner.contextMenuModule.locale.getConstant('Add to Dictionary') ? 'Add to Dictionary' : str), iconCss: '' }); } } return spellSuggestion; }; /** * Method to check whether text element has errors * * @private */ SpellChecker.prototype.checktextElementHasErrors = function (text, element, left) { var hasError = false; var erroElements = []; text = text.replace(/[\s]+/g, ''); if (!isNullOrUndefined(element.errorCollection) && element.errorCollection.length > 0) { if (!this.documentHelper.isScrollHandler && (element.ischangeDetected || element.paragraph.isChangeDetected) && !element.istextCombined) { this.updateStatusForGlobalErrors(element.errorCollection, element); element.errorCollection = []; element.ischangeDetected = true; return { 'errorFound': hasError, 'elements': erroElements }; } for (var i = 0; i < element.errorCollection.length; i++) { if (this.handleErrorCollection(element.errorCollection[i])) { hasError = true; erroElements.push(element.errorCollection[i]); } } } else if (!this.documentHelper.isScrollHandler && element.paragraph.isChangeDetected) { element.ischangeDetected = true; } else if (!element.ischangeDetected && this.handleErrorCollection(element)) { hasError = true; erroElements.push(element); } return { 'errorFound': hasError, 'elements': erroElements }; }; SpellChecker.prototype.updateStatusForGlobalErrors = function (erroElements, parentElement) { if (erroElements.length > 0) { for (var i = 0; i < erroElements.length; i++) { var exactText = this.manageSpecialCharacters(erroElements[i].text, undefined, true); if (this.errorWordCollection.containsKey(exactText)) { var elements = this.errorWordCollection.get(exactText); for (var j = 0; j < elements.length; j++) { if (elements[j] instanceof ErrorTextElementBox && elements[j] === erroElements[i]) { elements[j].ischangeDetected = true; elements[j].start.offset = parentElement.line.getOffset(parentElement.istextCombined ? this.getCombinedElement(parentElement) : parentElement, 0); elements[j].line = parentElement.line; break; } } } } } }; /** * Method to handle document error collection. * * @param {string} errorInElement * @private */ SpellChecker.prototype.handleErrorCollection = function (errorInElement) { var errors = this.errorWordCollection; var exactText = this.manageSpecialCharacters(errorInElement.text, undefined, true); if (errors.containsKey(exactText) && errorInElement.length > 1) { var ignoreAllIndex = this.ignoreAllItems.indexOf(exactText); if (ignoreAllIndex > -1) { if (errors.containsKey(exactText)) { errors.remove(exactText); } return false; } return true; } return false; }; /* eslint-disable @typescript-eslint/no-explicit-any */ SpellChecker.prototype.constructInlineMenu = function (inlineSuggestion) { for (var i = inlineSuggestion.length - 1; i > 0; i--) { if (inlineSuggestion.length > 3) { this.spellCheckSuggestion.push(inlineSuggestion[i]); inlineSuggestion.pop(); } } return inlineSuggestion; }; /** * Method to retrieve error element text * * @private */ SpellChecker.prototype.findCurretText = function () { var insertPosition = this.documentHelper.selection.start; /* eslint-disable @typescript-eslint/no-explicit-any */ var element; /* eslint-disable @typescript-eslint/no-explicit-any */ var inlineObj = insertPosition.currentWidget.getInline(this.documentHelper.selection.start.offset, 0); var text; if (!isNullOrUndefined(inlineObj.element)) { if (!isNullOrUndefined(inlineObj.element.errorCollection) && inlineObj.element.errorCollection.length > 0) { for (var i = 0; i < inlineObj.element.errorCollection.length; i++) { var errorElement = inlineObj.element.errorCollection[i]; if (errorElement.start.isExistBefore(this.documentHelper.selection.start) && errorElement.end.isExistAfter(this.documentHelper.selection.start)) { text = errorElement.text; element = errorElement; break; } } } else { text = inlineObj.element.text; } if (text === ' ') { inlineObj = insertPosition.currentWidget.getInline(this.documentHelper.selection.start.offset + 1, 0); text = inlineObj.element.text; } } return { 'text': text, 'element': element }; }; SpellChecker.prototype.addErrorCollection = function (text, elementToCompare, suggestions) { text = this.manageSpecialCharacters(text, undefined, true); if (this.errorWordCollection.containsKey(text)) { var errorElements = this.errorWordCollection.get(text); if (elementToCompare instanceof ErrorTextElementBox) { if (!this.compareErrorTextElement(elementToCompare, errorElements)) { errorElements.push(elementToCompare); } } else if (elementToCompare instanceof TextElementBox) { if (!this.compareTextElement(elementToCompare, errorElements)) { errorElements.push(elementToCompare); } } } else { if (!isNullOrUndefined(suggestions) && suggestions.length > 0) { this.errorSuggestions.add(text, suggestions); } this.errorWordCollection.add(text, [elementToCompare]); if (!this.uniqueWordsCollection.containsKey(text)) { this.uniqueWordsCollection.add(text, true); } } }; SpellChecker.prototype.addCorrectWordCollection = function (text) { text = this.manageSpecialCharacters(text, undefined, true); if (!this.uniqueWordsCollection.containsKey(text)) { this.uniqueWordsCollection.add(text, false); } }; /** * @private */ SpellChecker.prototype.isInUniqueWords = function (text) { text = text.replace(/[\s]+/g, ''); return this.uniqueWordsCollection.containsKey(text); }; /** * @private */ SpellChecker.prototype.isErrorWord = function (text) { text = text.replace(/[\s]+/g, ''); return this.uniqueWordsCollection.get(text); }; /** * @private */ SpellChecker.prototype.isCorrectWord = function (text) { text = text.replace(/[\s]+/g, ''); return !this.uniqueWordsCollection.get(text); }; SpellChecker.prototype.compareErrorTextElement = function (errorElement, errorCollection) { var copyElement = []; var isChanged = false; for (var i = 0; i < errorCollection.length; i++) { copyElement.push(errorCollection[i]); } var length = errorCollection.length; for (var i = 0; i < length; i++) { if (copyElement[i] instanceof ErrorTextElementBox) { if (copyElement[i].ischangeDetected) { var exactText = this.manageSpecialCharacters(copyElement[i].text, undefined, true); isChanged = true; this.removeErrorsFromCollection({ 'element': copyElement[i], 'text': exactText }); } else { var currentElement = copyElement[i]; if (errorElement.start.offset === currentElement.start.offset && errorElement.end.offset === currentElement.end.offset) { return true; } } } } if (isChanged) { this.errorWordCollection.add(this.manageSpecialCharacters(errorElement.text, undefined, true), [errorElement]); } return false; }; /** * Method to compare text elements * * @private */ SpellChecker.prototype.compareTextElement = function (errorElement, errorCollection) { for (var i = 0; i < errorCollection.length; i++) { if (errorCollection[i] instanceof TextElementBox) { var currentElement = errorCollection[i]; if (currentElement === errorElement) { return true; } } } return false; }; /** * Method to handle Word by word spell check * * @private */ SpellChecker.prototype.handleWordByWordSpellCheck = function (jsonObject, elementBox, left, top, underlineY, baselineAlignment, isSamePage, currentText) { if (isNullOrUndefined(currentText)) { currentText = elementBox.text; } if (jsonObject.HasSpellingError && isSamePage) { this.addErrorCollection(currentText, elementBox, jsonObject.Suggestions); if (currentText === elementBox.text.trim()) { var backgroundColor = (elementBox.line.paragraph.containerWidget instanceof TableCellWidget) ? elementBox.line.paragraph.containerWidget.cellFormat.shading.backgroundColor : this.documentHelper.backgroundColor; this.documentHelper.render.renderWavyLine(elementBox, left, top, underlineY, '#FF0000', 'Single', baselineAlignment, backgroundColor); elementBox.isSpellChecked = true; } } else { this.addCorrectWordCollection(currentText); elementBox.isSpellChecked = true; } }; /** * Method to check errors for combined elements * * @private */ SpellChecker.prototype.checkElementCanBeCombined = function (elementBox, underlineY, beforeIndex, callSpellChecker, textToCombine, isNext, isPrevious, canCombine) { var currentText = isNullOrUndefined(textToCombine) ? '' : textToCombine; var isCombined = isNullOrUndefined(canCombine) ? false : canCombine; var checkPrevious = !isNullOrUndefined(isPrevious) ? isPrevious : true; var checkNext = !isNullOrUndefined(isNext) ? isNext : true; var line = this.documentHelper.selection.getLineWidget(elementBox, 0); var index = line.children.indexOf(elementBox); var prevText = elementBox.text; if (this.combinedElements.indexOf(elementBox) === -1) { this.combinedElements.push(elementBox); } var difference = (isPrevious) ? 0 : 1; var prevCombined = false; var isPrevField = false; if (elementBox.text !== '\v') { if (checkPrevious) { var textElement = undefined; for (var i = index - difference; i >= 0; i--) { textElement = line.children[i]; if (!isNullOrUndefined(textElement) && !isNullOrUndefined(textElement.revisions) && textElement.revisions.length > 0 && textElement.revisions[0].revisionType === "Deletion") { break; } if (textElement instanceof TextElementBox && !isPrevField) { if (prevText.indexOf(' ') !== 0 && textElement.text.lastIndexOf(' ') !== textElement.text.length - 1) { prevCombined = !isNullOrUndefined(textToCombine) ? true : false; currentText = textElement.text + currentText; prevText = textElement.text; isPrevField = false; if (this.combinedElements.indexOf(textElement) === -1) { this.combinedElements.push(textElement); } isCombined = true; } else if (!isNullOrUndefined(textElement)) { textElement = textElement.nextElement; break; } } else if (textElement instanceof FieldElementBox && textElement.fieldType !== 1) { isPrevField = true; } } var currentElement = (isCombined) ? textElement : elementBox; if (this.lookThroughPreviousLine(currentText, prevText, currentElement, underlineY, beforeIndex)) { this.combinedElements.length = 0; return true; } } if (isPrevious) { currentText = (prevCombined) ? currentText : elementBox.text + currentText; } else { currentText += elementBox.text; } isPrevField = false; var nextText = elementBox.text; if (checkNext) { var canCombine_1 = false; var element = undefined; for (var i = index + 1; i < line.children.length; i++) { element = line.children[i]; if (!isNullOrUndefined(element) && !isNullOrUndefined(element.revisions) && element.revisions.length > 0 && element.revisions[0].revisionType === "Deletion") { break; } if (element instanceof TextElementBox && !isPrevField) { if (nextText.lastIndexOf(' ') !== nextText.length - 1 && element.text.indexOf(' ') !== 0) { currentText += element.text; nextText = element.text; isPrevField = false; this.combinedElements.push(element); canCombine_1 = true; isCombined = true; } else if (!isNullOrUndefined(element)) { element = element.previousElement; break; } } else if (element instanceof FieldElementBox && element.fieldType !== 2) { isPrevField = true; } } var currentElement = (canCombine_1) ? element : elementBox; if (currentElement.text !== '\f' && currentElement.text !== String.fromCharCode(14) && this.lookThroughNextLine(currentText, prevText, currentElement, underlineY, beforeIndex)) { this.combinedElements.length = 0; return true; } } } if (isCombined && callSpellChecker && !this.checkCombinedElementsBeIgnored(this.combinedElements, currentText)) { if (isPrevious || isNext) { for (var i = 0; i < this.combinedElements.length; i++) { if (i !== 0) { this.combinedElements[i].istextCombined = true; this.combinedElements[i].errorCollection = this.combinedElements[0].errorCollection; } } } else { this.combinedElements.length = 0; } this.handleCombinedElements(elementBox, currentText, underlineY); } this.combinedElements.length = 0; return isCombined; }; SpellChecker.prototype.lookThroughPreviousLine = function (currentText, prevText, currentElement, underlineY, beforeIndex) { if (!isNullOrUndefined(currentElement) && currentElement.indexInOwner === 0 && !isNullOrUndefined(currentElement.line.previousLine)) { var previousLine = currentElement.line.previousLine; var index = previousLine.children.length - 1; if (!isNullOrUndefined(previousLine.children[index]) && previousLine.children[index] instanceof TextElementBox) { var firstElement = previousLine.children[index]; if (!isNullOrUndefined(currentElement.text)) { if (currentElement.text.indexOf(' ') !== 0 && firstElement.text.lastIndexOf(' ') !== firstElement.text.length - 1) { currentText = (currentText.length > 0) ? currentText : prevText; this.checkElementCanBeCombined(firstElement, underlineY, beforeIndex, true, currentText, false, true, true); return true; } } } } return false; }; SpellChecker.prototype.lookThroughNextLine = function (currentText, prevText, elementBox, underlineY, beforeIndex) { if (elementBox instanceof TextElementBox && !isNullOrUndefined(elementBox) && elementBox.indexInOwner === elementBox.line.children.length - 1 && !isNullOrUndefined(elementBox.line.nextLine)) { var nextLine = elementBox.line.nextLine; if (!isNullOrUndefined(nextLine.children[0]) && nextLine.children[0] instanceof TextElementBox) { var firstElement = nextLine.children[0]; if (elementBox.text.lastIndexOf(' ') !== elementBox.text.length - 1 && firstElement.text.indexOf(' ') !== 0) { currentText = (currentText.length > 0) ? currentText : prevText; this.checkElementCanBeCombined(firstElement, underlineY, beforeIndex, true, currentText, true, false, true); return true; } } } return false; }; /** * Method to handle combined elements * * @param {TextElementBox} elementBox * @param {string} currentText * @param {number} underlineY * @param {number} beforeIndex * @private */ SpellChecker.prototype.handleCombinedElements = function (elementBox, currentText, underlineY) { var splittedText = currentText.split(/[\s]+/); if (this.ignoreAllItems.indexOf(currentText) === -1 && elementBox instanceof TextElementBox && elementBox.ignoreOnceItems.indexOf(currentText) === -1) { if (splittedText.length > 1) { for (var i = 0; i < splittedText.length; i++) { var currentText_1 = splittedText[i]; currentText_1 = this.manageSpecialCharacters(currentText_1, undefined, true); this.documentHelper.render.handleUnorderedElements(currentText_1, elementBox, underlineY, i, 0, i === splittedText.length - 1, this.combinedElements); } } else { currentText = this.manageSpecialCharacters(currentText, undefined, true); this.documentHelper.render.handleUnorderedElements(currentText, elementBox, underlineY, 0, 0, true, this.combinedElements); } } }; /** * Method to check error element collection has unique element * * @param {ErrorTextElementBox[]} errorCollection * @param {ErrorTextElementBox} elementToCheck * @private */ SpellChecker.prototype.checkArrayHasSameElement = function (errorCollection, elementToCheck) { for (var i = 0; i < errorCollection.length; i++) { var errorText = errorCollection[i]; if ((errorText.start.location.x === elementToCheck.start.location.x) && (errorText.start.location.y === elementToCheck.start.location.y)) { return true; } } return false; }; /** * @private */ SpellChecker.prototype.handleSplitWordSpellCheck = function (jsonObject, currentText, elementBox, isSamePage, underlineY, iteration, markIndex, isLastItem, combinedElements) { if (jsonObject.HasSpellingError && elementBox.text !== ' ' && isSamePage) { var textSearch = this.documentHelper.owner.searchModule.textSearch; var matchResults = this.getMatchedResultsFromElement(elementBox, currentText); if (elementBox.previousElement instanceof FieldElementBox && elementBox.previousElement.fieldType === 1) { matchResults.elementInfo.values.pop(); matchResults.elementInfo.values.push(0); } // Handled combined elements split to multiple lines when textResults is empty. // Only the first element will be rendered with wavy line. Other elements will be rendered in renderTextElementBox method in render Element. if (!isNullOrUndefined(combinedElements) && matchResults.textResults.length === 0 && combinedElements.length > 0) { var combinedElement = combinedElements[0]; matchResults = this.getMatchedResultsFromElement(combinedElement, combinedElement.text); markIndex = combinedElement.line.getOffset(this.getCombinedElement(combinedElement), 0); textSearch.updateMatchedTextLocation(matchResults.matches, matchResults.textResults, matchResults.elementInfo, 0, combinedElement, false, null, markIndex); this.handleMatchedResults(matchResults.textResults, combinedElement, underlineY, iteration, jsonObject.Suggestions, false, currentText, combinedElements); } else { markIndex = (elementBox.istextCombined) ? elementBox.line.getOffset(this.getCombinedElement(elementBox), 0) : markIndex; textSearch.updateMatchedTextLocation(matchResults.matches, matchResults.textResults, matchResults.elementInfo, 0, elementBox, false, null, markIndex); this.handleMatchedResults(matchResults.textResults, elementBox, underlineY, iteration, jsonObject.Suggestions, isLastItem); } } else { this.addCorrectWordCollection(currentText); if (isLastItem) { elementBox.isSpellChecked = true; } } this.updateUniqueWord([{ Text: currentText, HasSpellError: jsonObject.HasSpellingError }]); }; SpellChecker.prototype.handleMatchedResults = function (results, elementBox, wavyLineY, index, suggestions, isLastItem, errorText, combinedElements) { if (results.length === 0 && isLastItem) { elementBox.isSpellChecked = true; return; } for (var i = 0; i < results.length; i++) { var span = this.createErrorElementWithInfo(results.innerList[i], elementBox); // Updated the error text and text position for combined elements. if (!isNullOrUndefined(errorText)) { span.text = errorText; var startElement = combinedElements[0]; var endElement = combinedElements[combinedElements.length - 1]; if (startElement && endElement) { var offset = startElement.line.getOffset(startElement, 0); var startPosition = new TextPosition(this.documentHelper.owner); startPosition.setPositionParagraph(startElement.line, offset); offset = endElement.line.getOffset(endElement, (endElement.length)); var endPosition = new TextPosition(this.documentHelper.owner); endPosition.setPositionParagraph(endElement.line, offset); span.start = startPosition; span.end = endPosition; } } var color = '#FF0000'; if (!isNullOrUndefined(elementBox.errorCollection) && !this.checkArrayHasSameElement(elementBox.errorCollection, span)) { elementBox.errorCollection.splice(index, 0, span); } this.addErrorCollection(span.text, span, suggestions); var elements = this.errorWordCollection.get(span.text); if (!isNullOrUndefined(elements) && elements.indexOf(elementBox) !== -1 && elements.indexOf(elementBox) !== elements.indexOf(span)) { elements.splice(elements.indexOf(elementBox), 1); } var backgroundColor = (elementBox.line.paragraph.containerWidget instanceof TableCellWidget) ? elementBox.paragraph.containerWidget.cellFormat.shading.backgroundColor : this.documentHelper.backgroundColor; var para = elementBox.line.paragraph; var lineY = para.y; for (var i_1 = 0; i_1 < para.childWidgets.length; i_1++) { if (para.childWidgets[i_1] == elementBox.line) break; lineY += para.childWidgets[i_1].height; } if (elementBox.isRightToLeft) { this.documentHelper.render.renderWavyLine(span, span.end.location.x, lineY, wavyLineY, color, 'Single', elementBox.characterFormat.baselineAlignment, backgroundColor); } else { this.documentHelper.render.renderWavyLine(span, span.start.location.x, lineY, wavyLineY, color, 'Single', elementBox.characterFormat.baselineAlignment, backgroundColor); } if (isLastItem) { elementBox.isSpellChecked = true; } } }; /** * Calls the spell checker service. * @private */ /* eslint-disable @typescript-eslint/no-explicit-any */ SpellChecker.prototype.callSpellChecker = function (languageID, word, checkSpelling, checkSuggestion, addWord, isByPage) { var _this = this; var spellchecker = this; return new Promise(function (resolve, reject) { if (!isNullOrUndefined(_this)) { var httpRequest_1 = new XMLHttpRequest(); var service_1 = _this.documentHelper.owner.serviceUrl; service_1 = (isByPage) ? service_1 + _this.documentHelper.owner.serverActionSettings.spellCheckByPage : service_1 + _this.documentHelper.owner.serverActionSettings.spellCheck; httpRequest_1.open('POST', service_1, true); httpRequest_1.setRequestHeader('Content-Type', 'application/json'); var headers = _this.documentHelper.owner.headers; /* eslint-disable @typescript-eslint/no-explicit-any */ if (isByPage) { word = word.replace(String.fromCharCode(160), ' '); } var spellCheckData = { LanguageID: languageID, TexttoCheck: word, CheckSpelling: checkSpelling, CheckSuggestion: checkSuggestion, AddWord: addWord }; var httprequestEventArgs = { serverActionType: 'SpellCheck', headers: headers, timeout: 0, cancel: false, withCredentials: false }; headers = httprequestEventArgs.headers; _this.documentHelper.owner.trigger(beforeXmlHttpRequestSend, httprequestEventArgs); _this.setCustomHeaders(httpRequest_1, httprequestEventArgs.headers); httpRequest_1.withCredentials = httprequestEventArgs.withCredentials; if (!httprequestEventArgs.cancel) { httpRequest_1.send(JSON.stringify(spellCheckData)); } httpRequest_1.onreadystatechange = function () { if (httpRequest_1.readyState === 4) { if (httpRequest_1.status === 200 || httpRequest_1.status === 304) { resolve(httpRequest_1.response); } else { var result = { status: httpRequest_1.status.toString(), statusText: httpRequest_1.responseText, url: service_1 }; result.name = 'onFailure'; if (!isNullOrUndefined(spellchecker.documentHelper)) { spellchecker.documentHelper.owner.fireServiceFailure(result); } reject(httpRequest_1.response); } } }; } }); }; SpellChecker.prototype.setCustomHeaders = function (httpRequest, headers) { if (!isNullOrUndefined(headers)) { for (var i = 0; i < headers.length; i++) { var header = headers[i]; for (var _i = 0, _a = Object.keys(header); _i < _a.length; _i++) { var key = _a[_i]; httpRequest.setRequestHeader(key, header[key]); } } } }; /** * Method to check for next error * * @private * @returns {void} */ SpellChecker.prototype.checkForNextError = function () { if (!isNullOrUndefined(this.viewer)) { var errorWords = this.errorWordCollection; if (errorWords.length > 0) { for (var i = 0; i < errorWords.length; i++) { var errorElements = errorWords.get(errorWords.keys[i]); for (var j = 0; j < errorElements.length; j++) { if (er