/*
* (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(window, undefined)
{
/**
* Plugin config.
* @typed {Object} Config
*
* @pr {string} name
* Plugin name which will be visible at the plugin toolbar.
*
* @pr {?Object} nameLocale
* Translations for the name field. The object keys are the two letter language codes (ru, de, it, etc.) and the values are the plugin name translation for each language. Example: { "fr" : "trFr", "de" : "deTr" }.
*
* @pr {string} guid
* Plugin identifier. It must be of the asc.{UUID} type.
*
* @pr {?string} [baseUrl=""]
* Path to the plugin. All the other paths are calculated relative to this path. In case the plugin is installed on the server, an additional parameter (path to the plugins) is added there. If baseUrl == "", the path to all plugins will be used.
*
* @pr {Variation[]} variations
* Plugin variations, or subplugins, that are created inside the origin plugin.
*/
/**
* The editors which the plugin is available for:
* word - text document editor,
* cell - spreadsheet editor,
* slide - presentation editor,
* pdf - pdf editor.
* @typedef {("word" | "cell" | "slide" | "pdf")} editorType
* @see office-js-api/Examples/Plugins/{Editor}/Enumeration/editorType.js
*/
/**
* The data type selected in the editor and sent to the plugin:
* text - the text data,
* html - HTML formatted code,
* ole - OLE object data,
* desktop - the desktop editor data,
* destop-external - the main page data of the desktop app (system messages),
* none - no data will be send to the plugin from the editor,
* sign - the sign for the keychain plugin.
* @typedef {("text" | "html" | "ole" | "desktop" | "destop-external" | "none" | "sign")} initDataType
* @see office-js-api/Examples/Plugins/{Editor}/Enumeration/initDataType.js
*/
/**
* Plugin event ("onDocumentContentReady", "onTargetPositionChanged", onClick", "onInputHelperClear", "onInputHelperInput", etc.).
* @typedef {string} EventType
* @see office-js-api/Examples/Plugins/{Editor}/Enumeration/EventType.js
*/
/**
* Plugin variations, or subplugins, that are created inside the origin plugin.
* @typed {Object} Variation
* @pr {string} description
* The description, i.e. what describes your plugin the best way.
*
* @pr {?Object} descriptionLocale
* Translations for the description field. The object keys are the two letter language codes (ru, de, it, etc.) and the values are the plugin description translation for each language.
*
* @pr {string} url
* Plugin entry point, i.e. an HTML file which connects the plugin.js file (the base file needed for work with plugins) and launches the plugin code.
*
* @pr {string[]} icons (with support HiDPI)
* Plugin icon image files used in the editors. There can be several scaling types for plugin icons: 100%, 125%, 150%, 175%, 200%, etc.
*
* @pr {?boolean} [isViewer=true]
* Specifies if the plugin is working when the document is available in the viewer mode only or not.
*
* @pr {boolean} isDisplayedInViewer
* Specifies if the plugin will be displayed in the viewer mode as well as in the editor mode (isDisplayedInViewer == true) or in the editor mode only (isDisplayedInViewer == false).
*
* @pr {EditorType[]} EditorsSupport
* The editors which the plugin is available for ("word" - text document editor, "cell" - spreadsheet editor, "slide" - presentation editor).
*
* @pr {boolean} [isVisual=true]
* Specifies if the plugin is visual (will open a window for some action, or introduce some additions to the editor panel interface) or non-visual (will provide a button (or buttons) which is going to apply some transformations or manipulations to the document).
*
* @pr {boolean} [isModal=true]
* Specifies if the opened plugin window is modal (used for visual plugins only, and if isInsideMode is not true).
*
* @pr {boolean} [isInsideMode=false]
* Specifies if the plugin must be displayed inside the editor panel instead of its own window.
*
* @pr {boolean} isCustomWindow
* Specifies if the plugin uses a custom window, without standard borders and buttons (used for modal plugins only).
*
* @pr {boolean} isSystem
* Specifies if the plugin is not displayed in the editor interface and is started in the background with the server (or desktop editors start) not interfering with the other plugins, so that they can work simultaneously.
*
* @pr {initDataType} initDataType
* The data type selected in the editor and sent to the plugin: "text" - the text data, "html" - HTML formatted code, "ole" - OLE object data, "desktop" - the desktop editor data, "destop-external" - the main page data of the desktop app (system messages), "none" - no data will be send to the plugin from the editor.
*
* @pr {string} initData
* Is usually equal to "" - this is the data which is sent from the editor to the plugin at the plugin start (e.g. if initDataType == "text", the plugin will receive the selected text when run). It may also be equal to encryption in the encryption plugins.
*
* @pr {?boolean} isUpdateOleOnResize
* Specifies if an OLE object must be redrawn when resized in the editor using the vector object draw type or not (used for OLE objects only, i.e. initDataType == "ole").
*
* @pr {?Button[]} buttons
* The list of skinnable plugin buttons used in the plugin interface (used for visual plugins with their own window only, i.e. isVisual == true && isInsideMode == false).
*
* @pr {?boolean} [initOnSelectionChanged=true]
* Specifies if the plugin watches the text selection events in the editor window.
*
* @pr {number[]} size
* Plugin window size.
*
* @pr {EventType[]} events
* Plugin events.
*/
/**
* The skinnable plugin button used in the plugin interface (used for visual plugins with their own window only, i.e. isVisual == true and isInsideMode == false).
* @typedef { Object } Button
* @property {string} text - The label which is displayed on the button.
* @property {boolean} [primary] - Defines if the button is primary or not. The primary flag affects the button skin only.
* @property {boolean} [isViewer] - Defines if the button is shown in the viewer mode only or not.
* @property {localeTranslate} [textLocale] - Translations for the text field. The object keys are the two letter language codes (ru, de, it, etc.) and the values are the button label translation for each language.
* @see office-js-api/Examples/Plugins/{Editor}/Enumeration/Button.js
*/
/**
* The OLE object properties
* @typedef {Object} OLEProperties
* @property {string} data - OLE object data (internal format).
* @property {string} imgSrc - A link to the image (its visual representation) stored in the OLE object and used by the plugin.
* @property {string} guid - An identifier of the plugin which can edit the current OLE object and must be of the *asc.{UUID}* type.
* @property {number} width - The OLE object width measured in millimeters.
* @property {number} height - The OLE object height measured in millimeters.
* @property {number} widthPix - The OLE object image width in pixels.
* @property {number} heightPix - The OLE object image height in pixels.
* @see office-js-api/Examples/Plugins/{Editor}/Enumeration/OLEProperties.js
*/
/**
* Base class
* @global
* @class
* @name Api
*/
var Api = window["AscCommon"].baseEditorsApi;
/**
* Returns the editor version.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias GetVersion
* @returns {string} - The editor version.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/GetVersion.js
*/
Api.prototype["pluginMethod_GetVersion"] = function() { return this.GetVersion(); };
/**
* Adds an OLE object to the current document position.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias AddOleObject
* @this Api
* @param {OLEProperties} data - The OLE object properties.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/AddOleObject.js
*/
Api.prototype["pluginMethod_AddOleObject"] = function(data) { return this.asc_addOleObject(data); };
/**
* Edits an OLE object in the document.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias EditOleObject
* @param {OLEProperties} data - The OLE object properties.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/EditOleObject.js
*/
Api.prototype["pluginMethod_EditOleObject"] = function(data) { return this.asc_editOleObject(data); };
/**
* Returns an array of the selected OLE objects.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias GetSelectedOleObjects
* @returns {OLEProperties[]} - An array of the *OLEProperties* objects containing the data about the OLE object parameters.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/GetSelectedOleObjects.js
*/
Api.prototype["pluginMethod_GetSelectedOleObjects"] = function()
{
let oDrawingsController = this.getGraphicController();
let aRes = [];
if(!oDrawingsController) return aRes;
let aSelectedOle = oDrawingsController.getSelectedOleObjects();
for(let nIdx = 0; nIdx < aSelectedOle.length; ++nIdx)
{
aRes.push(aSelectedOle[nIdx].getPluginDataObject());
}
return aRes;
};
/**
* An object containing the font information.
* @typedef {Object} FontInfo
* @property {string} m_wsFontName The font name.
* @property {string} m_wsFontPath The path to the file with the current font.
* @property {number} m_lIndex The font number in the file if there is more than one font in the file.
* @property {boolean} m_bBold Specifies if the font characters are bold or not.
* @property {boolean} m_bItalic Specifies if the font characters are italic or not.
* @property {boolean} m_bIsFixed Specifies if the current font is monospaced or not.
* @property {Array.} m_aPanose The PANOSE Typeface Classification Number, a compact 10-byte description of the font critical visual characteristics, such as contrast, weight, and serif style.
* @property {number} m_ulUnicodeRange1 The Unicode range encompassed by the font file (Bits 0-31).
* @property {number} m_ulUnicodeRange2 The Unicode range encompassed by the font file (Bits 32-63).
* @property {number} m_ulUnicodeRange3 The Unicode range encompassed by the font file (Bits 64-95).
* @property {number} m_ulUnicodeRange4 The Unicode range encompassed by the font file (Bits 96-127).
* @property {number} m_ulCodePageRange1 The code pages encompassed by the font file (Bits 0-31).
* @property {number} m_ulCodePageRange2 The code pages encompassed by the font file (Bits 32-63).
* @property {number} m_usWeigth The visual weight (stroke blackness or thickness) of the font characters (1-1000).
* @property {number} m_usWidth The relative change from the normal aspect ratio (width to height ratio).
* @property {number} m_sFamilyClass The font family class which values are assigned by IBM to each font family.
* @property {number} m_eFontFormat The specific file type(s) used to store font data: 0 - *.fon, 1 - *.ttf, 2 - *.ttf, *.otf (CFF), 3 - unknown font format.
* @property {number} m_shAvgCharWidth The arithmetic average of the escapement (width) of all non-zero width glyphs in the font.
* @property {number} m_shAscent The height above the baseline for a clipping region.
* @property {number} m_shDescent The vertical extent below the baseline for a clipping region.
* @property {number} m_shLineGap The typographic line gap for the current font.
* @property {number} m_shXHeight The distance between the baseline and the approximate height of non-ascending lowercase letters measured in FUnits.
* @property {number} m_shCapHeight The distance between the baseline and the approximate height of uppercase letters measured in FUnits.
* @see office-js-api/Examples/Plugins/{Editor}/Enumeration/FontInfo.js
*/
/**
* Returns the fonts list.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias GetFontList
* @returns {FontInfo[]} - An array of the FontInfo objects containing the data about the used fonts.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/GetFontList.js
*/
Api.prototype["pluginMethod_GetFontList"] = function()
{
return AscFonts.g_fontApplication.g_fontSelections.SerializeList();
};
/**
* Inserts text into the document.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias InputText
* @param {string} text - A string value that specifies the text to be inserted into the document.
* @param {string} textReplace - A string value that specifies the text to be replaced with a new text.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/InputText.js
*/
Api.prototype["pluginMethod_InputText"] = function(text, textReplace)
{
if (!this.canEdit() || this.isPdfEditor() || !AscCommon.g_inputContext)
return;
if (textReplace)
{
for (var i = 0; i < textReplace.length; i++)
AscCommon.g_inputContext.emulateKeyDownApi(8);
}
AscCommon.g_inputContext.addText(text);
AscCommon.g_inputContext.keyPressInput = "";
};
/**
* Pastes text in the HTML format into the document.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias PasteHtml
* @param {string} htmlText - A string value that specifies the text in the *HTML* format to be pasted into the document.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/PasteHtml.js
*/
Api.prototype["pluginMethod_PasteHtml"] = function (htmlText) {
if (!AscCommon.g_clipboardBase)
return null;
if (!this.canEdit() || this.isPdfEditor())
return null;
let _elem = document.getElementById("pmpastehtml");
if (_elem)
return;
window.g_asc_plugins && window.g_asc_plugins.setPluginMethodReturnAsync();
_elem = document.createElement("div");
_elem.id = "pmpastehtml";
_elem.style.color = "rgb(0,0,0)";
if (this.editorId === AscCommon.c_oEditorId.Word || this.editorId === AscCommon.c_oEditorId.Presentation) {
let textPr = this.get_TextProps();
if (textPr) {
if (undefined !== textPr.TextPr.FontSize)
_elem.style.fontSize = textPr.TextPr.FontSize + "pt";
_elem.style.fontWeight = (true === textPr.TextPr.Bold) ? "bold" : "normal";
_elem.style.fontStyle = (true === textPr.TextPr.Italic) ? "italic" : "normal";
let _color = textPr.TextPr.Color;
if (_color)
_elem.style.color = "rgb(" + _color.r + "," + _color.g + "," + _color.b + ")";
else
_elem.style.color = "rgb(0,0,0)";
}
} else if (this.editorId === AscCommon.c_oEditorId.Spreadsheet) {
let props = this.asc_getCellInfo();
if (props && props.font) {
if (undefined != props.font.size)
_elem.style.fontSize = props.font.size + "pt";
_elem.style.fontWeight = (true === props.font.bold) ? "bold" : "normal";
_elem.style.fontStyle = (true === props.font.italic) ? "italic" : "normal";
}
}
_elem.innerHTML = htmlText;
document.body.appendChild(_elem);
this.incrementCounterLongAction();
let b_old_save_format = AscCommon.g_clipboardBase.bSaveFormat;
AscCommon.g_clipboardBase.bSaveFormat = false;
let _t = this;
this.asc_PasteData(AscCommon.c_oAscClipboardDataFormat.HtmlElement, _elem, undefined, undefined, undefined,
function () {
_t.decrementCounterLongAction();
let fCallback = function () {
document.body.removeChild(_elem);
_elem = null;
AscCommon.g_clipboardBase.bSaveFormat = b_old_save_format;
};
if (_t.checkLongActionCallback(fCallback, null)) {
fCallback();
}
window.g_asc_plugins && window.g_asc_plugins.onPluginMethodReturn(true);
}
);
};
/**
* Pastes text into the document.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias PasteText
* @param {string} text - A string value that specifies the text to be pasted into the document.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/PasteText.js
*/
Api.prototype["pluginMethod_PasteText"] = function(text)
{
if (!AscCommon.g_clipboardBase)
return null;
this.asc_PasteData(AscCommon.c_oAscClipboardDataFormat.Text, text);
};
/**
* An object containing the data about all the macros from the document.
* @typedef {Object} Macros
* @property {Array.} macrosArray - An array of macros codes (*[{"name": "Macros1", "value": "{macrosCode}"}]*).
* @property {number} current - A current macro index.
* @see office-js-api/Examples/Plugins/{Editor}/Enumeration/Macros.js
*/
/**
* Returns the document macros.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias GetMacros
* @returns {Macros} - The Macros object containing the data about all the macros from the document
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/GetMacros.js
*/
Api.prototype["pluginMethod_GetMacros"] = function()
{
return this.asc_getMacros();
};
/**
* Sets macros to the document.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias SetMacros
* @param {Macros} data - The *Macros* object containing the data about all the macros from the document.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/SetMacros.js
*/
Api.prototype["pluginMethod_SetMacros"] = function(data)
{
return this.asc_setMacros(data);
};
/**
* Returns all VBA macros from the document.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias GetVBAMacros
* @returns {string | null} VBA xml macros.
* @since 7.3.0
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/GetVBAMacros.js
*/
Api.prototype["pluginMethod_GetVBAMacros"] = function()
{
return (this.vbaProject ? this.vbaProject.vbaXml : null);
};
/**
* Specifies the start action for long operations.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias StartAction
* @param {number} type - A value which defines an action type which can take 0 if this is an *Information* action or 1 if this is a *BlockInteraction* action.
* @param {string} description - A string value that specifies the description text for the start action of the operation.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/StartAction.js
*/
Api.prototype["pluginMethod_StartAction"] = function(type, description)
{
this.sync_StartAction((type == "Block") ? Asc.c_oAscAsyncActionType.BlockInteraction : Asc.c_oAscAsyncActionType.Information, description);
};
/**
* Specifies the end action for long operations.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias EndAction
* @param {number} type - A value which defines an action type which can take "Block" if this is the *BlockInteraction* action or "Information if this is the *Information* action.
* @param {string} description - A string value that specifies the description text for the operation end action.
* @param {string} status - The error status code. If no error occurs, then an empty string is passed.
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/EndAction.js
*/
Api.prototype["pluginMethod_EndAction"] = function(type, description, status)
{
this.sync_EndAction((type == "Block") ? Asc.c_oAscAsyncActionType.BlockInteraction : Asc.c_oAscAsyncActionType.Information, description);
if (window["AscDesktopEditor"] && status != null && status != "")
{
// error!!!
if (!window["AscDesktopEditor"]["IsLocalFile"]())
{
this.sendEvent("asc_onError", "Encryption error: " + status + ". The file was not compiled.", c_oAscError.Level.Critical);
window["AscDesktopEditor"]["CryptoMode"] = 0;
}
else
{
this.sendEvent("asc_onError", "Encryption error: " + status + ". End-to-end encryption mode is disabled.", c_oAscError.Level.NoCritical);
window["AscDesktopEditor"]["CryptoMode"] = 0;
if (undefined !== window.LastUserSavedIndex)
{
AscCommon.History.UserSavedIndex = window.LastUserSavedIndex;
if (this.editorId == AscCommon.c_oEditorId.Spreadsheet)
this.onUpdateDocumentModified(AscCommon.History.Have_Changes());
else
this.UpdateInterfaceState();
}
}
window.LastUserSavedIndex = undefined;
setTimeout(function() {
window["AscDesktopEditor"]["buildCryptedEnd"](false);
}, 500);
return;
}
window.LastUserSavedIndex = undefined;
if (this._callbackPluginEndAction)
{
this._callbackPluginEndAction.call(this);
}
};
/**
* Encrypts the document.
* @memberof Api
* @typeofeditors ["CDE", "CSE", "CPE"]
* @alias OnEncryption
* @param {object} obj - The encryption properties.
* @param {string} obj.type - The type of encrypting operation:
* generatePassword - generates a password for the document,
* getPasswordByFile - sends the password when opening the document,
* encryptData - encrypts changes when co-editing,
* decryptData - decrypts changes when co-editing.
* @param {string} obj.password - A string value specifying the password to access the document.
* @param {string} obj.data - Encrypted/decrypted changes.
* @param {boolean} obj.check - Checks if the encryption/decryption operation is successful or not (used only for *encryptData* or *decryptData* types).
* @param {string} obj.docinfo - An unencrypted part of the encrypted file.
* @param {string} obj.hash - A string value specifying a file hash (*sha256* by default).
* @param {string} obj.error - A string value specifying an error that occurs (the "" value means that the operation is successful).
* @see office-js-api/Examples/Plugins/{Editor}/Api/Methods/OnEncryption.js
*/
Api.prototype["pluginMethod_OnEncryption"] = function(obj)
{
var _editor = window["Asc"]["editor"] ? window["Asc"]["editor"] : window.editor;
switch (obj.type)
{
case "generatePassword":
{
if ("" == obj["password"])
{
_editor.sendEvent("asc_onError", "There is no connection with the blockchain", c_oAscError.Level.Critical);
return;
}
if ("no_build" === obj["error"])
{
// проблемы - но такие, при которых просто не собираем файл...
window["AscDesktopEditor"]["buildCryptedEnd"](true);
return;
}
var _ret = _editor.getFileAsFromChanges();
AscCommon.EncryptionWorker.isPasswordCryptoPresent = true;
_editor.currentDocumentInfoNext = obj["docinfo"];
window["AscDesktopEditor"]["buildCryptedStart"](_ret.data, _ret.header, obj["password"], obj["docinfo"] ? obj["docinfo"] : "");
break;
}
case "getPasswordByFile":
{
if ("" != obj["password"])
{
var _param = ("" + AscCommon.CopyPasteCorrectString(obj["password"]) + "");
_editor.currentPassword = obj["password"];
_editor.currentDocumentHash = obj["hash"];
_editor.currentDocumentInfo = obj["docinfo"];
AscCommon.EncryptionWorker.isPasswordCryptoPresent = true;
if (window.isNativeOpenPassword)
{
window["AscDesktopEditor"]["NativeViewerOpen"](obj["password"]);
}
else
{
window["AscDesktopEditor"]["SetAdvancedOptions"](_param);
}
}
else
{
this._onNeedParams({ message : obj["message"] }, true);
}
break;
}
case "encryptData":
case "decryptData":
{
AscCommon.EncryptionWorker.receiveChanges(obj);
break;
}
}
};
/**
* An object containing the watermark properties.
* @typedef {Object} watermark_on_draw
* @property {number} transparent The watermark transparency degree.
* @property {string} type The {@link /docbuilder/global#ShapeType shape type} which specifies the preset shape geometry for the current watermark.
* @property {number} width The watermark width measured in millimeters.
* @property {number} height The watermark height measured in millimeters.
* @property {number} rotate The watermark rotation angle measured in degrees.
* @property {Array.} margins The text margins measured in millimeters in the watermark shape.
* @property {Array. | string} fill The watermark fill color in the RGB format, or the URL to image (base64 support: data:image/png;...). The empty array [] means that the watermark has no fill.
* @property {number} stroke-width The watermark stroke width measured in millimeters.
* @property {Array.} stroke The watermark stroke color in the RGB format. The empty array [] means that the watermark stroke has no fill.
* @property {number} align The vertical text align in the watermark shape: 0 - bottom, 1 - center, 4 - top.
* @property {Array.