@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapui5/sap.ui.richtexteditor",
3
- "version": "1.143.0",
3
+ "version": "1.144.0",
4
4
  "description": "SAPUI5 Library sap.ui.richtexteditor",
5
5
  "homepage": "https://ui5.github.io/cli/pages/SAPUI5/",
6
6
  "author": "SAP SE (https://www.sap.com)",
@@ -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.143.0</version>
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
 
@@ -24,7 +24,7 @@ sap.ui.define([
24
24
  * @alias sap.ui.richtexteditor.RTESplitButton
25
25
  *
26
26
  * @author SAP SE
27
- * @version 1.143.0
27
+ * @version 1.144.0
28
28
  */
29
29
  var RTESplitButton = SplitButton.extend("sap.ui.richtexteditor.RTESplitButton", {
30
30
  metadata: {
@@ -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
- var bIsTinyMCE6or7 = this.getEditorType() === RichTextEditor.EDITORTYPE_TINYMCE6 || this.getEditorType() === RichTextEditor.EDITORTYPE_TINYMCE || this.getEditorType() === RichTextEditor.EDITORTYPE_TINYMCE7;
1879
-
1880
- // since TinyMCE 6 plugins property format has changed
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 (bIsTinyMCE6or7 && !this.getEditable()) {
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 = bIsTinyMCE6or7 ? RichTextEditor.SUPPORTED_LANGUAGES_DEFAULT_REGIONS_TINYMCE7[sLanguage] : RichTextEditor.SUPPORTED_LANGUAGES_DEFAULT_REGIONS[sLanguage];
1992
+ sRegion = RichTextEditor.SUPPORTED_LANGUAGES_DEFAULT_REGIONS_TINYMCE7[sLanguage];
2001
1993
  }
2002
1994
 
2003
1995
  sLangStr = sRegion ? sLanguage + "_" + sRegion.toUpperCase() : sLanguage;
@@ -22,7 +22,7 @@ sap.ui.define([
22
22
  * @extends sap.ui.core.Element
23
23
  *
24
24
  * @author SAP SE
25
- * @version 1.143.0
25
+ * @version 1.144.0
26
26
  *
27
27
  * @public
28
28
  * @alias sap.ui.richtexteditor.RichTextEditorFontFamily
@@ -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
- oSelectedNode = this._getSelectionAnchor(oSelection);
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
- // if there isn't a selection or a link is partly selected,
906
- // the display text should be equal to the text of the selection node
907
- if (!bSelection || bLinkPartSelected) {
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
- var oNativeEditor = this.getEditor().getNativeApi();
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 and no link selected, do not generate an anchor
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
- // if the user modifies the predefined text value of the current node via the dialog we should perform insertContent
1238
- if (sText !== this.sSelectionTextValue || sText === "") {
1239
- oNativeEditor.insertContent(oNativeEditor.dom.createHTML('a', oLinkAttrs, oNativeEditor.dom.encode(sText)));
1342
+ if (bImageSelected) {
1343
+ this._handleImageLink(oSelectedNode, oLinkAttrs);
1240
1344
  } else {
1241
- oNativeEditor.execCommand('mceInsertLink', false, oLinkAttrs);
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
- if (oRTE.getEditorType() === library.EditorType.TinyMCE6 || oRTE.getEditorType() === library.EditorType.TinyMCE7) {
1454
- oNativeAPI.execCommand('mceInsertTable', false, { rows: iRows, columns: iCols });
1557
+ oNativeAPI.execCommand('mceInsertTable', false, { rows: iRows, columns: iCols });
1455
1558
 
1456
- oTableElm = oDomRef.getParents(oNativeAPI.selection.getNode()).find(function (element) {
1457
- return element.tagName.toLowerCase() === "table";
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");
@@ -37,7 +37,7 @@ sap.ui.define([
37
37
  "sap.ui.richtexteditor.RTESplitButton"
38
38
  ],
39
39
  elements: [],
40
- version: "1.143.0"
40
+ version: "1.144.0"
41
41
  });
42
42
 
43
43
  /**
@@ -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 teksta
24
+ TEXTALIGN_BUTTON_TOOLTIP=Poravnava besedila
25
25
 
26
26
  #XTOL: Tooltip for text formatBlock menu button
27
27
  FORMAT_BUTTON_TOOLTIP=Oblika