@sapui5/sap.ui.richtexteditor 1.143.0 → 1.144.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/sap/ui/richtexteditor/.library +1 -1
- package/src/sap/ui/richtexteditor/RTESplitButton.js +1 -1
- package/src/sap/ui/richtexteditor/RichTextEditor.js +7 -15
- package/src/sap/ui/richtexteditor/RichTextEditorFontFamily.js +1 -1
- package/src/sap/ui/richtexteditor/ToolbarWrapper.js +120 -20
- package/src/sap/ui/richtexteditor/library.js +1 -1
- package/src/sap/ui/richtexteditor/messagebundle_sl.properties +1 -1
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<vendor>SAP SE</vendor>
|
|
6
6
|
<copyright>SAPUI5
|
|
7
7
|
* (c) Copyright 2025 SAP SE. All rights reserved.</copyright>
|
|
8
|
-
<version>1.
|
|
8
|
+
<version>1.144.0</version>
|
|
9
9
|
|
|
10
10
|
<documentation>A rich text editor (RTE) control. Requires installation of an additional rich text editor library.</documentation>
|
|
11
11
|
|
|
@@ -380,7 +380,7 @@ sap.ui.define([
|
|
|
380
380
|
_toolbarWrapper: {type: "sap.ui.richtexteditor.IToolbar", multiple: false, visibility : "hidden", defaultValue: null},
|
|
381
381
|
/**
|
|
382
382
|
* Custom buttons are meant to extend the <code>RichTextEditor</code>'s custom toolbar.
|
|
383
|
-
* Though type is set to sap.ui.Control, only sap.m.Button is allowed.
|
|
383
|
+
* Though type is set to sap.ui.core.Control, only sap.m.Button is allowed.
|
|
384
384
|
* <b>Note:</b> customButtons are available only when the <code>customToolbar</code> is enabled and all the requirements are fulfilled.
|
|
385
385
|
*
|
|
386
386
|
* @since 1.48
|
|
@@ -1283,8 +1283,6 @@ sap.ui.define([
|
|
|
1283
1283
|
this.setProperty("editorType", sEditorType);
|
|
1284
1284
|
sEditorType = this.getEditorType();
|
|
1285
1285
|
|
|
1286
|
-
this._setupToolbar();
|
|
1287
|
-
|
|
1288
1286
|
if (!oEditorMapping[sEditorType]) {
|
|
1289
1287
|
this.setProperty("editorType", RichTextEditor.EDITORTYPE_TINYMCE);
|
|
1290
1288
|
Log.error('Invalid editorType value set. Fallbacks to latest.');
|
|
@@ -1297,6 +1295,7 @@ sap.ui.define([
|
|
|
1297
1295
|
Log.error("TinyMCE version 6 is used as editor type. TinyMCE 6 is deprecated as of version 1.141.0 and will be removed from the code entirely in near future.");
|
|
1298
1296
|
}
|
|
1299
1297
|
|
|
1298
|
+
this._setupToolbar();
|
|
1300
1299
|
this.initTinyMCE();
|
|
1301
1300
|
} else {
|
|
1302
1301
|
Log.error(
|
|
@@ -1875,17 +1874,11 @@ sap.ui.define([
|
|
|
1875
1874
|
sPluginsList = sPluginsList.replace(/(,powerpaste|powerpaste,)/gi, "");
|
|
1876
1875
|
}
|
|
1877
1876
|
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
if (bIsTinyMCE6or7) {
|
|
1882
|
-
sPluginsList = this.getPlugins().map(function(oPlugin) {
|
|
1883
|
-
return oPlugin.name;
|
|
1884
|
-
});
|
|
1885
|
-
}
|
|
1886
|
-
|
|
1877
|
+
sPluginsList = this.getPlugins().map(function(oPlugin) {
|
|
1878
|
+
return oPlugin.name;
|
|
1879
|
+
});
|
|
1887
1880
|
|
|
1888
|
-
if (
|
|
1881
|
+
if (!this.getEditable()) {
|
|
1889
1882
|
sPluginsList = sPluginsList.filter(function(oPlugin) {
|
|
1890
1883
|
return oPlugin !== "powerpaste";
|
|
1891
1884
|
});
|
|
@@ -1989,7 +1982,6 @@ sap.ui.define([
|
|
|
1989
1982
|
var oLocale = new Locale(Localization.getLanguage()),
|
|
1990
1983
|
sLanguage = oLocale.getLanguage(),
|
|
1991
1984
|
sRegion = oLocale.getRegion(),
|
|
1992
|
-
bIsTinyMCE6or7 = this.getEditorType() === RichTextEditor.EDITORTYPE_TINYMCE6 || this.getEditorType() === RichTextEditor.EDITORTYPE_TINYMCE || this.getEditorType() === RichTextEditor.EDITORTYPE_TINYMCE7,
|
|
1993
1985
|
sLangStr;
|
|
1994
1986
|
|
|
1995
1987
|
// Language mapping for old/fallback languages
|
|
@@ -1997,7 +1989,7 @@ sap.ui.define([
|
|
|
1997
1989
|
|
|
1998
1990
|
// Find default region, if region is not given
|
|
1999
1991
|
if (!sRegion) {
|
|
2000
|
-
sRegion =
|
|
1992
|
+
sRegion = RichTextEditor.SUPPORTED_LANGUAGES_DEFAULT_REGIONS_TINYMCE7[sLanguage];
|
|
2001
1993
|
}
|
|
2002
1994
|
|
|
2003
1995
|
sLangStr = sRegion ? sLanguage + "_" + sRegion.toUpperCase() : sLanguage;
|
|
@@ -873,7 +873,7 @@ sap.ui.define([
|
|
|
873
873
|
var aDialogContent = oDialog && oDialog.getContent(),
|
|
874
874
|
oSelection, oSelectedNode, sURL, sDisplayText, sTitle,
|
|
875
875
|
bTarget, oSelectionNode, bLinkPartSelected, bSelection,
|
|
876
|
-
sUrlInputPrefixValue;
|
|
876
|
+
sUrlInputPrefixValue, bImageSelected;
|
|
877
877
|
|
|
878
878
|
if (!(aDialogContent instanceof Array) || !aDialogContent.length) {
|
|
879
879
|
return;
|
|
@@ -881,7 +881,15 @@ sap.ui.define([
|
|
|
881
881
|
|
|
882
882
|
oSelection = this.getEditor().getNativeApi().selection;
|
|
883
883
|
oSelectionNode = oSelection.getNode();
|
|
884
|
-
|
|
884
|
+
|
|
885
|
+
bImageSelected = oSelectionNode && oSelectionNode.tagName &&
|
|
886
|
+
oSelectionNode.tagName.toLowerCase() === "img";
|
|
887
|
+
|
|
888
|
+
if (bImageSelected) {
|
|
889
|
+
oSelectedNode = this._getImageAnchor(oSelectionNode);
|
|
890
|
+
} else {
|
|
891
|
+
oSelectedNode = this._getSelectionAnchor(oSelection);
|
|
892
|
+
}
|
|
885
893
|
|
|
886
894
|
if (!oSelectedNode) {
|
|
887
895
|
oSelectedNode = oSelectionNode.parentElement;
|
|
@@ -902,9 +910,17 @@ sap.ui.define([
|
|
|
902
910
|
this._bLinkPrefixChecked = oSelectedNode.getAttribute('data-sap-ui-rte-link-prefix') === "true";
|
|
903
911
|
}
|
|
904
912
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
913
|
+
if (bImageSelected) {
|
|
914
|
+
// For images, check if there's an existing link with title, otherwise use alt text
|
|
915
|
+
const oImageAnchor = this._getImageAnchor(oSelectionNode);
|
|
916
|
+
if (oImageAnchor && oImageAnchor.getAttribute('title')) {
|
|
917
|
+
sDisplayText = oImageAnchor.getAttribute('title');
|
|
918
|
+
} else {
|
|
919
|
+
sDisplayText = oSelectionNode.getAttribute('alt') || '';
|
|
920
|
+
}
|
|
921
|
+
} else if (!bSelection || bLinkPartSelected) {
|
|
922
|
+
// if there isn't a selection or a link is partly selected,
|
|
923
|
+
// the display text should be equal to the text of the selection node
|
|
908
924
|
sDisplayText = oSelectedNode.text;
|
|
909
925
|
} else {
|
|
910
926
|
// prevents displaying the whole anchor element as a display text
|
|
@@ -1143,13 +1159,15 @@ sap.ui.define([
|
|
|
1143
1159
|
|
|
1144
1160
|
/**
|
|
1145
1161
|
* Helper function for finding selected anchor HTML node
|
|
1162
|
+
* @param {object} oSelection TinyMCE selection object
|
|
1163
|
+
* @returns {HTMLAnchorElement|null} The selected anchor element or null
|
|
1146
1164
|
* @private
|
|
1147
1165
|
*/
|
|
1148
1166
|
ToolbarWrapper.prototype._getSelectionAnchor = function (oSelection) {
|
|
1149
1167
|
var oSelectionNode, oAnchor;
|
|
1150
1168
|
|
|
1151
1169
|
if (!oSelection) {
|
|
1152
|
-
return;
|
|
1170
|
+
return null;
|
|
1153
1171
|
}
|
|
1154
1172
|
|
|
1155
1173
|
oSelectionNode = oSelection.getNode();
|
|
@@ -1163,6 +1181,83 @@ sap.ui.define([
|
|
|
1163
1181
|
return oAnchor;
|
|
1164
1182
|
};
|
|
1165
1183
|
|
|
1184
|
+
/**
|
|
1185
|
+
* Helper function for finding anchor element that wraps an image
|
|
1186
|
+
* @param {HTMLImageElement} oImageElement The image element
|
|
1187
|
+
* @returns {HTMLAnchorElement|null} The wrapping anchor element or null
|
|
1188
|
+
* @private
|
|
1189
|
+
*/
|
|
1190
|
+
ToolbarWrapper.prototype._getImageAnchor = function (oImageElement) {
|
|
1191
|
+
const oParent = oImageElement && oImageElement.parentElement;
|
|
1192
|
+
return (oParent && oParent.tagName && oParent.tagName.toLowerCase() === "a") ? oParent : null;
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* Handles creating text links in the editor
|
|
1197
|
+
* @param {string} sText The text content for the link
|
|
1198
|
+
* @param {object} oLinkAttrs Link attributes (href, title, target)
|
|
1199
|
+
* @private
|
|
1200
|
+
*/
|
|
1201
|
+
ToolbarWrapper.prototype._handleTextLink = function (sText, oLinkAttrs) {
|
|
1202
|
+
const oNativeEditor = this.getEditor().getNativeApi();
|
|
1203
|
+
|
|
1204
|
+
if (sText !== this.sSelectionTextValue || sText === "") {
|
|
1205
|
+
oNativeEditor.insertContent(oNativeEditor.dom.createHTML('a', oLinkAttrs, oNativeEditor.dom.encode(sText)));
|
|
1206
|
+
} else {
|
|
1207
|
+
oNativeEditor.execCommand('mceInsertLink', false, oLinkAttrs);
|
|
1208
|
+
}
|
|
1209
|
+
};
|
|
1210
|
+
|
|
1211
|
+
/**
|
|
1212
|
+
* Handles wrapping an image with a link or updating an existing image link
|
|
1213
|
+
* @param {HTMLImageElement} oImageElement The image element to link
|
|
1214
|
+
* @param {object} oLinkAttrs Link attributes (href, title, target)
|
|
1215
|
+
* @private
|
|
1216
|
+
*/
|
|
1217
|
+
ToolbarWrapper.prototype._handleImageLink = function (oImageElement, oLinkAttrs) {
|
|
1218
|
+
const oNativeEditor = this.getEditor().getNativeApi();
|
|
1219
|
+
const oExistingAnchor = this._getImageAnchor(oImageElement);
|
|
1220
|
+
|
|
1221
|
+
if (!oExistingAnchor) {
|
|
1222
|
+
const oLinkElement = oNativeEditor.dom.create("a", oLinkAttrs);
|
|
1223
|
+
oNativeEditor.dom.insertAfter(oLinkElement, oImageElement);
|
|
1224
|
+
oLinkElement.appendChild(oImageElement);
|
|
1225
|
+
oNativeEditor.selection.select(oLinkElement);
|
|
1226
|
+
} else {
|
|
1227
|
+
this._updateImageLinkAttributes(oExistingAnchor, oLinkAttrs);
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* Updates the attributes of an existing image link
|
|
1233
|
+
* @param {HTMLAnchorElement} oAnchorElement The anchor element to update
|
|
1234
|
+
* @param {object} oLinkAttrs Link attributes to update
|
|
1235
|
+
* @private
|
|
1236
|
+
*/
|
|
1237
|
+
ToolbarWrapper.prototype._updateImageLinkAttributes = function (oAnchorElement, oLinkAttrs) {
|
|
1238
|
+
if (oLinkAttrs.href) {
|
|
1239
|
+
oAnchorElement.setAttribute("href", oLinkAttrs.href);
|
|
1240
|
+
}
|
|
1241
|
+
if (oLinkAttrs.title) {
|
|
1242
|
+
oAnchorElement.setAttribute("title", oLinkAttrs.title);
|
|
1243
|
+
}
|
|
1244
|
+
if (oLinkAttrs.target) {
|
|
1245
|
+
oAnchorElement.setAttribute("target", oLinkAttrs.target);
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1249
|
+
/**
|
|
1250
|
+
* Removes the link wrapper from an image element
|
|
1251
|
+
* @param {HTMLImageElement} oImageElement The image element
|
|
1252
|
+
* @param {HTMLAnchorElement} oAnchorElement The anchor element wrapping the image
|
|
1253
|
+
* @private
|
|
1254
|
+
*/
|
|
1255
|
+
ToolbarWrapper.prototype._removeImageLink = function (oImageElement, oAnchorElement) {
|
|
1256
|
+
const oNativeEditor = this.getEditor().getNativeApi();
|
|
1257
|
+
oNativeEditor.dom.insertAfter(oImageElement, oAnchorElement);
|
|
1258
|
+
oNativeEditor.dom.remove(oAnchorElement);
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1166
1261
|
/**
|
|
1167
1262
|
* Validates and sanitizes a user-provided link field (URL) for safe usage in HTML links.
|
|
1168
1263
|
* - Validates URL syntax and safety
|
|
@@ -1227,18 +1322,27 @@ sap.ui.define([
|
|
|
1227
1322
|
* @private
|
|
1228
1323
|
*/
|
|
1229
1324
|
ToolbarWrapper.prototype.createLink = function (oLinkAttrs, sText) {
|
|
1230
|
-
|
|
1325
|
+
const oNativeEditor = this.getEditor().getNativeApi();
|
|
1326
|
+
const oSelectedNode = oNativeEditor.selection.getNode();
|
|
1327
|
+
const bImageSelected = oSelectedNode && oSelectedNode.tagName &&
|
|
1328
|
+
oSelectedNode.tagName.toLowerCase() === "img";
|
|
1231
1329
|
|
|
1232
|
-
// if there is no url provided
|
|
1330
|
+
// if there is no url provided
|
|
1233
1331
|
if (oLinkAttrs.href === "") {
|
|
1332
|
+
// check if an image is already wrapped in a link and remove it
|
|
1333
|
+
if (bImageSelected) {
|
|
1334
|
+
const oExistingAnchor = this._getImageAnchor(oSelectedNode);
|
|
1335
|
+
if (oExistingAnchor) {
|
|
1336
|
+
this._removeImageLink(oSelectedNode, oExistingAnchor);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1234
1339
|
return;
|
|
1235
1340
|
}
|
|
1236
1341
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
oNativeEditor.insertContent(oNativeEditor.dom.createHTML('a', oLinkAttrs, oNativeEditor.dom.encode(sText)));
|
|
1342
|
+
if (bImageSelected) {
|
|
1343
|
+
this._handleImageLink(oSelectedNode, oLinkAttrs);
|
|
1240
1344
|
} else {
|
|
1241
|
-
|
|
1345
|
+
this._handleTextLink(sText, oLinkAttrs);
|
|
1242
1346
|
}
|
|
1243
1347
|
};
|
|
1244
1348
|
|
|
@@ -1450,15 +1554,11 @@ sap.ui.define([
|
|
|
1450
1554
|
const iRows = Math.min(Math.max(oRowsInput.getValue(), iMinTableCells), iMaxTableCells);
|
|
1451
1555
|
const iCols = Math.min(Math.max(oColsInput.getValue(), iMinTableCells), iMaxTableCells);
|
|
1452
1556
|
|
|
1453
|
-
|
|
1454
|
-
oNativeAPI.execCommand('mceInsertTable', false, { rows: iRows, columns: iCols });
|
|
1557
|
+
oNativeAPI.execCommand('mceInsertTable', false, { rows: iRows, columns: iCols });
|
|
1455
1558
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
} else {
|
|
1460
|
-
oTableElm = oNativeAPI.plugins.table.insertTable(iCols, iRows);
|
|
1461
|
-
}
|
|
1559
|
+
oTableElm = oDomRef.getParents(oNativeAPI.selection.getNode()).find(function (element) {
|
|
1560
|
+
return element.tagName.toLowerCase() === "table";
|
|
1561
|
+
});
|
|
1462
1562
|
|
|
1463
1563
|
oDomRef.setStyle(oTableElm, 'width', oDimensionWidthInput.getValue() + "px");
|
|
1464
1564
|
oDomRef.setStyle(oTableElm, 'height', oDimensionHeightInput.getValue() + "px");
|
|
@@ -21,7 +21,7 @@ UNDERLINE_BUTTON_TOOLTIP=Pod\u010Drtano
|
|
|
21
21
|
STRIKETHROUGH_BUTTON_TOOLTIP=Pre\u010Drtano
|
|
22
22
|
|
|
23
23
|
#XTOL: Tooltip for text align menu button
|
|
24
|
-
TEXTALIGN_BUTTON_TOOLTIP=Poravnava
|
|
24
|
+
TEXTALIGN_BUTTON_TOOLTIP=Poravnava besedila
|
|
25
25
|
|
|
26
26
|
#XTOL: Tooltip for text formatBlock menu button
|
|
27
27
|
FORMAT_BUTTON_TOOLTIP=Oblika
|