@sapui5/sap.fe.core 1.141.2 → 1.143.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.
Files changed (217) hide show
  1. package/package.json +1 -1
  2. package/src/sap/fe/core/.library +4 -1
  3. package/src/sap/fe/core/ActionRuntime.js +78 -23
  4. package/src/sap/fe/core/ActionRuntime.ts +91 -35
  5. package/src/sap/fe/core/AppComponent.js +76 -6
  6. package/src/sap/fe/core/AppComponent.ts +91 -8
  7. package/src/sap/fe/core/AppStateHandler.js +7 -7
  8. package/src/sap/fe/core/AppStateHandler.ts +9 -8
  9. package/src/sap/fe/core/BaseController.js +8 -5
  10. package/src/sap/fe/core/BaseController.ts +6 -1
  11. package/src/sap/fe/core/CommonUtils.js +4 -123
  12. package/src/sap/fe/core/CommonUtils.ts +3 -172
  13. package/src/sap/fe/core/ExtensionAPI.js +3 -11
  14. package/src/sap/fe/core/ExtensionAPI.ts +3 -16
  15. package/src/sap/fe/core/PageController.js +64 -43
  16. package/src/sap/fe/core/PageController.ts +62 -47
  17. package/src/sap/fe/core/TemplateComponent.js +12 -1
  18. package/src/sap/fe/core/TemplateComponent.ts +16 -2
  19. package/src/sap/fe/core/buildingBlocks/BuildingBlock.js +37 -24
  20. package/src/sap/fe/core/buildingBlocks/BuildingBlock.ts +47 -31
  21. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockSupport.js +1 -1
  22. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockSupport.ts +4 -0
  23. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplateProcessor.js +4 -1
  24. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplateProcessor.ts +3 -0
  25. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplatingBase.js +5 -3
  26. package/src/sap/fe/core/buildingBlocks/templating/BuildingBlockTemplatingBase.ts +5 -2
  27. package/src/sap/fe/core/controllerextensions/BaseControllerExtension.js +7 -5
  28. package/src/sap/fe/core/controllerextensions/BaseControllerExtension.ts +22 -2
  29. package/src/sap/fe/core/controllerextensions/CollaborativeDraft.js +82 -44
  30. package/src/sap/fe/core/controllerextensions/CollaborativeDraft.ts +92 -59
  31. package/src/sap/fe/core/controllerextensions/EditFlow.js +74 -48
  32. package/src/sap/fe/core/controllerextensions/EditFlow.ts +87 -50
  33. package/src/sap/fe/core/controllerextensions/InlineEditFlow.js +9 -7
  34. package/src/sap/fe/core/controllerextensions/InlineEditFlow.ts +17 -5
  35. package/src/sap/fe/core/controllerextensions/InternalRouting.js +37 -18
  36. package/src/sap/fe/core/controllerextensions/InternalRouting.ts +49 -17
  37. package/src/sap/fe/core/controllerextensions/KPIManagement.js +30 -15
  38. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +32 -14
  39. package/src/sap/fe/core/controllerextensions/MessageHandler.js +9 -10
  40. package/src/sap/fe/core/controllerextensions/MessageHandler.ts +10 -9
  41. package/src/sap/fe/core/controllerextensions/Paginator.js +2 -2
  42. package/src/sap/fe/core/controllerextensions/Paginator.ts +1 -1
  43. package/src/sap/fe/core/controllerextensions/Placeholder.js +10 -2
  44. package/src/sap/fe/core/controllerextensions/Placeholder.ts +5 -1
  45. package/src/sap/fe/core/controllerextensions/Recommendations.js +3 -3
  46. package/src/sap/fe/core/controllerextensions/Recommendations.ts +2 -2
  47. package/src/sap/fe/core/controllerextensions/Routing.js +4 -4
  48. package/src/sap/fe/core/controllerextensions/Routing.ts +3 -6
  49. package/src/sap/fe/core/controllerextensions/Share.js +5 -5
  50. package/src/sap/fe/core/controllerextensions/Share.ts +4 -4
  51. package/src/sap/fe/core/controllerextensions/SideEffects.js +1 -1
  52. package/src/sap/fe/core/controllerextensions/SideEffects.ts +17 -2
  53. package/src/sap/fe/core/controllerextensions/collaboration/ActivityBase.js +2 -2
  54. package/src/sap/fe/core/controllerextensions/collaboration/ActivityBase.ts +1 -1
  55. package/src/sap/fe/core/controllerextensions/editFlow/NotApplicableContextDialog.js +3 -3
  56. package/src/sap/fe/core/controllerextensions/editFlow/NotApplicableContextDialog.tsx +3 -2
  57. package/src/sap/fe/core/controllerextensions/editFlow/TransactionHelper.js +49 -21
  58. package/src/sap/fe/core/controllerextensions/editFlow/TransactionHelper.ts +64 -24
  59. package/src/sap/fe/core/controllerextensions/editFlow/draft.js +37 -3
  60. package/src/sap/fe/core/controllerextensions/editFlow/draft.ts +41 -8
  61. package/src/sap/fe/core/controllerextensions/editFlow/draftDataLossPopup.js +10 -4
  62. package/src/sap/fe/core/controllerextensions/editFlow/draftDataLossPopup.ts +6 -1
  63. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataOperation.js +6 -7
  64. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataOperation.ts +5 -5
  65. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataStrictHandling.js +2 -2
  66. package/src/sap/fe/core/controllerextensions/editFlow/operations/ODataStrictHandling.ts +1 -1
  67. package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationMessage.js +2 -1
  68. package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationMessage.ts +1 -0
  69. package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationParameters.js +2 -1
  70. package/src/sap/fe/core/controllerextensions/editFlow/operations/OperationParameters.ts +1 -0
  71. package/src/sap/fe/core/controllerextensions/messageHandler/messageHandling.js +21 -15
  72. package/src/sap/fe/core/controllerextensions/messageHandler/messageHandling.ts +18 -15
  73. package/src/sap/fe/core/controllerextensions/routing/RouterProxy.js +7 -6
  74. package/src/sap/fe/core/controllerextensions/routing/RouterProxy.ts +8 -5
  75. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DraftDataLossDialog.js +9 -4
  76. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DraftDataLossDialog.tsx +10 -4
  77. package/src/sap/fe/core/controls/Recommendations/ConfirmRecommendationDialog.js +3 -2
  78. package/src/sap/fe/core/controls/Recommendations/ConfirmRecommendationDialog.tsx +2 -1
  79. package/src/sap/fe/core/converters/ManifestSettings.js +7 -1
  80. package/src/sap/fe/core/converters/ManifestSettings.ts +37 -0
  81. package/src/sap/fe/core/converters/ManifestWrapper.js +29 -9
  82. package/src/sap/fe/core/converters/ManifestWrapper.ts +29 -11
  83. package/src/sap/fe/core/converters/MetaModelConverter.js +1 -1
  84. package/src/sap/fe/core/converters/MetaModelConverter.ts +1 -1
  85. package/src/sap/fe/core/converters/annotations/DataField.js +46 -19
  86. package/src/sap/fe/core/converters/annotations/DataField.ts +93 -19
  87. package/src/sap/fe/core/converters/common/AnnotationConverter.js +118 -39
  88. package/src/sap/fe/core/converters/controls/Common/Action.js +58 -21
  89. package/src/sap/fe/core/converters/controls/Common/Action.ts +72 -22
  90. package/src/sap/fe/core/converters/controls/Common/Chart.js +13 -3
  91. package/src/sap/fe/core/converters/controls/Common/Chart.ts +20 -4
  92. package/src/sap/fe/core/converters/controls/Common/Form.js +18 -3
  93. package/src/sap/fe/core/converters/controls/Common/Form.ts +23 -1
  94. package/src/sap/fe/core/converters/controls/Common/Table.js +87 -22
  95. package/src/sap/fe/core/converters/controls/Common/Table.ts +112 -21
  96. package/src/sap/fe/core/converters/controls/Common/filter/FilterRestrictions.js +243 -0
  97. package/src/sap/fe/core/converters/controls/Common/filter/FilterRestrictions.ts +309 -0
  98. package/src/sap/fe/core/converters/controls/Common/table/Columns.js +142 -58
  99. package/src/sap/fe/core/converters/controls/Common/table/Columns.ts +174 -79
  100. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +7 -16
  101. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +6 -17
  102. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +16 -5
  103. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +16 -5
  104. package/src/sap/fe/core/converters/helpers/Aggregation.js +12 -2
  105. package/src/sap/fe/core/converters/helpers/Aggregation.ts +11 -1
  106. package/src/sap/fe/core/converters/helpers/DataFieldHelper.js +27 -3
  107. package/src/sap/fe/core/converters/helpers/DataFieldHelper.ts +28 -1
  108. package/src/sap/fe/core/converters/helpers/ID.js +3 -1
  109. package/src/sap/fe/core/converters/helpers/ID.ts +1 -0
  110. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +10 -5
  111. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +13 -1
  112. package/src/sap/fe/core/converters/templates/ListReportConverter.js +11 -3
  113. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +12 -4
  114. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +19 -8
  115. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +18 -7
  116. package/src/sap/fe/core/designtime/AnnotationBasedChanges.js +8 -3
  117. package/src/sap/fe/core/designtime/AnnotationBasedChanges.ts +7 -2
  118. package/src/sap/fe/core/flexibility/AppComponent.flexibility.js +55 -0
  119. package/src/sap/fe/core/flexibility/AppComponent.flexibility.ts +65 -0
  120. package/src/sap/fe/core/flexibility/XMLTools.js +71 -0
  121. package/src/sap/fe/core/flexibility/XMLTools.ts +61 -0
  122. package/src/sap/fe/core/fpm/manifest.json +2 -2
  123. package/src/sap/fe/core/helpers/AppStartupHelper.js +79 -25
  124. package/src/sap/fe/core/helpers/AppStartupHelper.ts +92 -32
  125. package/src/sap/fe/core/helpers/DeleteHelper.js +13 -13
  126. package/src/sap/fe/core/helpers/DeleteHelper.ts +17 -15
  127. package/src/sap/fe/core/helpers/ManifestHelper.js +6 -3
  128. package/src/sap/fe/core/helpers/ManifestHelper.ts +3 -0
  129. package/src/sap/fe/core/helpers/MetaModelFunction.js +12 -3
  130. package/src/sap/fe/core/helpers/MetaModelFunction.ts +11 -3
  131. package/src/sap/fe/core/helpers/ModelHelper.js +47 -11
  132. package/src/sap/fe/core/helpers/ModelHelper.ts +62 -15
  133. package/src/sap/fe/core/helpers/PasteHelper.js +6 -2
  134. package/src/sap/fe/core/helpers/PasteHelper.ts +5 -7
  135. package/src/sap/fe/core/helpers/TypeGuards.js +12 -2
  136. package/src/sap/fe/core/helpers/TypeGuards.ts +10 -1
  137. package/src/sap/fe/core/helpers/WebSocket.js +6 -7
  138. package/src/sap/fe/core/helpers/WebSocket.ts +10 -6
  139. package/src/sap/fe/core/library.js +33 -3
  140. package/src/sap/fe/core/library.ts +31 -1
  141. package/src/sap/fe/core/messagebundle.properties +8 -1
  142. package/src/sap/fe/core/messagebundle_ar.properties +8 -1
  143. package/src/sap/fe/core/messagebundle_bg.properties +10 -3
  144. package/src/sap/fe/core/messagebundle_ca.properties +7 -0
  145. package/src/sap/fe/core/messagebundle_cnr.properties +7 -0
  146. package/src/sap/fe/core/messagebundle_cs.properties +7 -0
  147. package/src/sap/fe/core/messagebundle_cy.properties +8 -1
  148. package/src/sap/fe/core/messagebundle_da.properties +7 -0
  149. package/src/sap/fe/core/messagebundle_de.properties +7 -0
  150. package/src/sap/fe/core/messagebundle_el.properties +7 -0
  151. package/src/sap/fe/core/messagebundle_en.properties +8 -1
  152. package/src/sap/fe/core/messagebundle_en_GB.properties +7 -0
  153. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +8 -1
  154. package/src/sap/fe/core/messagebundle_es.properties +8 -1
  155. package/src/sap/fe/core/messagebundle_es_MX.properties +7 -0
  156. package/src/sap/fe/core/messagebundle_et.properties +7 -0
  157. package/src/sap/fe/core/messagebundle_fi.properties +7 -0
  158. package/src/sap/fe/core/messagebundle_fr.properties +16 -9
  159. package/src/sap/fe/core/messagebundle_fr_CA.properties +7 -0
  160. package/src/sap/fe/core/messagebundle_hi.properties +8 -1
  161. package/src/sap/fe/core/messagebundle_hr.properties +7 -0
  162. package/src/sap/fe/core/messagebundle_hu.properties +7 -0
  163. package/src/sap/fe/core/messagebundle_id.properties +7 -0
  164. package/src/sap/fe/core/messagebundle_it.properties +7 -0
  165. package/src/sap/fe/core/messagebundle_iw.properties +7 -0
  166. package/src/sap/fe/core/messagebundle_ja.properties +8 -1
  167. package/src/sap/fe/core/messagebundle_kk.properties +7 -0
  168. package/src/sap/fe/core/messagebundle_ko.properties +7 -0
  169. package/src/sap/fe/core/messagebundle_lt.properties +7 -0
  170. package/src/sap/fe/core/messagebundle_lv.properties +7 -0
  171. package/src/sap/fe/core/messagebundle_mk.properties +7 -0
  172. package/src/sap/fe/core/messagebundle_ms.properties +7 -0
  173. package/src/sap/fe/core/messagebundle_nl.properties +7 -0
  174. package/src/sap/fe/core/messagebundle_no.properties +9 -2
  175. package/src/sap/fe/core/messagebundle_pl.properties +7 -0
  176. package/src/sap/fe/core/messagebundle_pt.properties +7 -0
  177. package/src/sap/fe/core/messagebundle_pt_PT.properties +7 -0
  178. package/src/sap/fe/core/messagebundle_ro.properties +7 -0
  179. package/src/sap/fe/core/messagebundle_ru.properties +7 -0
  180. package/src/sap/fe/core/messagebundle_sh.properties +7 -0
  181. package/src/sap/fe/core/messagebundle_sk.properties +7 -0
  182. package/src/sap/fe/core/messagebundle_sl.properties +7 -0
  183. package/src/sap/fe/core/messagebundle_sr.properties +7 -0
  184. package/src/sap/fe/core/messagebundle_sv.properties +7 -0
  185. package/src/sap/fe/core/messagebundle_th.properties +7 -0
  186. package/src/sap/fe/core/messagebundle_tr.properties +7 -0
  187. package/src/sap/fe/core/messagebundle_uk.properties +7 -0
  188. package/src/sap/fe/core/messagebundle_vi.properties +7 -0
  189. package/src/sap/fe/core/messagebundle_zh_CN.properties +8 -1
  190. package/src/sap/fe/core/messagebundle_zh_TW.properties +7 -0
  191. package/src/sap/fe/core/rootView/Fcl.controller.js +21 -7
  192. package/src/sap/fe/core/rootView/Fcl.controller.ts +22 -5
  193. package/src/sap/fe/core/rootView/NavContainer.controller.js +1 -1
  194. package/src/sap/fe/core/rootView/NavContainer.controller.ts +2 -1
  195. package/src/sap/fe/core/rootView/RootViewBaseController.js +96 -88
  196. package/src/sap/fe/core/rootView/RootViewBaseController.ts +106 -96
  197. package/src/sap/fe/core/services/CollaborativeToolsServiceFactory.js +1 -1
  198. package/src/sap/fe/core/services/CollaborativeToolsServiceFactory.ts +9 -9
  199. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +14 -10
  200. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +15 -10
  201. package/src/sap/fe/core/services/RoutingServiceFactory.js +9 -4
  202. package/src/sap/fe/core/services/RoutingServiceFactory.ts +13 -6
  203. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +9 -7
  204. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +13 -8
  205. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +57 -5
  206. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +69 -10
  207. package/src/sap/fe/core/services/collaborativeDraftServiceFactory.js +33 -15
  208. package/src/sap/fe/core/services/collaborativeDraftServiceFactory.ts +31 -11
  209. package/src/sap/fe/core/templating/DisplayModeFormatter.js +4 -5
  210. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +4 -6
  211. package/src/sap/fe/core/templating/UIFormatters.js +17 -2
  212. package/src/sap/fe/core/templating/UIFormatters.ts +25 -1
  213. package/src/sap/fe/core/types/sap.fe.core-auto-ext.d.js +10 -0
  214. package/src/sap/fe/core/types/sap.fe.core-auto-ext.d.ts +369 -0
  215. package/src/sap/fe/core/types/sap.fe.core-manual-ext.d.js +9 -0
  216. package/src/sap/fe/core/types/sap.fe.core-manual-ext.d.ts +49 -0
  217. package/ui5.yaml +2 -0
@@ -10,11 +10,11 @@ import Component from "sap/ui/core/Component";
10
10
  import Lib from "sap/ui/core/Lib";
11
11
  import type ODataModel from "sap/ui/model/odata/v4/ODataModel";
12
12
  // OK since we are in designtime we can ignore that dependency
13
+ import CommonUtils from "sap/fe/core/CommonUtils";
13
14
  import { hasCurrency, hasUnit, isCurrency, isUnit } from "sap/fe/core/templating/PropertyHelper";
14
15
  import type Field from "sap/fe/macros/Field";
15
16
  import type FormElement from "sap/ui/layout/form/FormElement";
16
17
  // eslint-disable-next-line @typescript-eslint/no-restricted-imports
17
- import CommonUtils from "sap/fe/core/CommonUtils";
18
18
  import AnnotationTypes from "sap/ui/rta/plugin/annotations/AnnotationTypes";
19
19
 
20
20
  const resourceBundleDesigntime = Lib.getResourceBundleFor("sap.fe.core.designtime")!;
@@ -95,7 +95,12 @@ function collectProperties(
95
95
  buildingBlock = buildingBlock.getParent();
96
96
  }
97
97
  let metaPath = contextPathToUse!;
98
- if (buildingBlock) {
98
+ if (control.getBindingContext()) {
99
+ const contextMetaPath = metaModel?.getMetaPath(control.getBindingContext()?.getPath() ?? "");
100
+ if (contextMetaPath) {
101
+ metaPath = contextMetaPath;
102
+ }
103
+ } else if (buildingBlock) {
99
104
  metaPath = buildingBlock.getProperty("metaPath") ?? contextPathToUse;
100
105
  }
101
106
  const properties: { property: Property; entityType: EntityType }[] = [];
@@ -0,0 +1,55 @@
1
+ /*!
2
+ * SAP UI development toolkit for HTML5 (SAPUI5)
3
+ * (c) Copyright 2009-2025 SAP SE. All rights reserved
4
+ */
5
+ sap.ui.define(["sap/base/Log", "sap/fe/core/CommonUtils", "sap/fe/core/flexibility/XMLTools", "sap/ui/core/Component", "sap/ui/fl/apply/api/DelegateMediatorAPI"], function (Log, CommonUtils, XMLTools, Component, DelegateMediatorAPI) {
6
+ "use strict";
7
+
8
+ var addGeneratedIdsToControls = XMLTools.addGeneratedIdsToControls;
9
+ /**
10
+ * Runs the provided fragment through the templating engine if the app component is an instance of sap.fe.core.AppComponent
11
+ * This will ensure that all included building blocks will be resolved to their target controls.
12
+ * @param fragment The XML fragment to be processed
13
+ * @param propertyBag An object containing the app component, modifier, view, and optionally componentId
14
+ * @param propertyBag.appComponent
15
+ * @param propertyBag.modifier
16
+ * @param propertyBag.view
17
+ * @param propertyBag.componentId
18
+ * @returns A promise that resolves to the processed XML fragment as a string
19
+ */
20
+ async function runTemplating(fragment, propertyBag) {
21
+ try {
22
+ if (propertyBag.appComponent.isA("sap.fe.core.AppComponent")) {
23
+ const templateComponent = propertyBag.componentId ? Component.getComponentById(propertyBag.componentId) : Component.getOwnerComponentFor(propertyBag.view);
24
+ const preprocessorContext = templateComponent?.preprocessorContext ?? {};
25
+ const fragmentXML = new DOMParser().parseFromString(fragment, "text/xml");
26
+ const templatedResult = await CommonUtils.templateControlFragment(fragmentXML.firstElementChild, {
27
+ models: preprocessorContext.models,
28
+ bindingContexts: preprocessorContext.bindingContexts
29
+ }, {
30
+ view: propertyBag.view,
31
+ isXML: true
32
+ }, propertyBag.modifier);
33
+ if (templatedResult instanceof Element) {
34
+ addGeneratedIdsToControls(templatedResult);
35
+ return templatedResult.outerHTML;
36
+ }
37
+ // If something goes wrong, fallback to the original fragment
38
+ return fragment;
39
+ } else {
40
+ return fragment;
41
+ }
42
+ } catch (error) {
43
+ Log.error("Error during Fiori Elements XML Templating in flexibility handler:", error);
44
+ return fragment;
45
+ }
46
+ }
47
+
48
+ // Register a hook onto the addXML handler from Flex that will run the templating if the conditions are right
49
+ DelegateMediatorAPI.registerAddXMLAdjustFragmentHandler({
50
+ key: "FEXMLTemplating",
51
+ handler: runTemplating,
52
+ reference: "sap.fe.macros.BaseAddXMLAdjustFragmentHandler"
53
+ });
54
+ }, false);
55
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJydW5UZW1wbGF0aW5nIiwiZnJhZ21lbnQiLCJwcm9wZXJ0eUJhZyIsImFwcENvbXBvbmVudCIsImlzQSIsInRlbXBsYXRlQ29tcG9uZW50IiwiY29tcG9uZW50SWQiLCJDb21wb25lbnQiLCJnZXRDb21wb25lbnRCeUlkIiwiZ2V0T3duZXJDb21wb25lbnRGb3IiLCJ2aWV3IiwicHJlcHJvY2Vzc29yQ29udGV4dCIsImZyYWdtZW50WE1MIiwiRE9NUGFyc2VyIiwicGFyc2VGcm9tU3RyaW5nIiwidGVtcGxhdGVkUmVzdWx0IiwiQ29tbW9uVXRpbHMiLCJ0ZW1wbGF0ZUNvbnRyb2xGcmFnbWVudCIsImZpcnN0RWxlbWVudENoaWxkIiwibW9kZWxzIiwiYmluZGluZ0NvbnRleHRzIiwiaXNYTUwiLCJtb2RpZmllciIsIkVsZW1lbnQiLCJhZGRHZW5lcmF0ZWRJZHNUb0NvbnRyb2xzIiwib3V0ZXJIVE1MIiwiZXJyb3IiLCJMb2ciLCJEZWxlZ2F0ZU1lZGlhdG9yQVBJIiwicmVnaXN0ZXJBZGRYTUxBZGp1c3RGcmFnbWVudEhhbmRsZXIiLCJrZXkiLCJoYW5kbGVyIiwicmVmZXJlbmNlIl0sInNvdXJjZVJvb3QiOiIuIiwic291cmNlcyI6WyJBcHBDb21wb25lbnQuZmxleGliaWxpdHkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IExvZyBmcm9tIFwic2FwL2Jhc2UvTG9nXCI7XG5pbXBvcnQgdHlwZSBBcHBDb21wb25lbnQgZnJvbSBcInNhcC9mZS9jb3JlL0FwcENvbXBvbmVudFwiO1xuaW1wb3J0IHR5cGUgeyBGRVZpZXcgfSBmcm9tIFwic2FwL2ZlL2NvcmUvQmFzZUNvbnRyb2xsZXJcIjtcbmltcG9ydCB0eXBlIHsgQmFzZVRyZWVNb2RpZmllciB9IGZyb20gXCJzYXAvZmUvY29yZS9Db21tb25VdGlsc1wiO1xuaW1wb3J0IENvbW1vblV0aWxzIGZyb20gXCJzYXAvZmUvY29yZS9Db21tb25VdGlsc1wiO1xuaW1wb3J0IHsgYWRkR2VuZXJhdGVkSWRzVG9Db250cm9scyB9IGZyb20gXCJzYXAvZmUvY29yZS9mbGV4aWJpbGl0eS9YTUxUb29sc1wiO1xuaW1wb3J0IHR5cGUgVGVtcGxhdGVDb21wb25lbnQgZnJvbSBcInNhcC9mZS9jb3JlL1RlbXBsYXRlQ29tcG9uZW50XCI7XG5pbXBvcnQgdHlwZSB7IFhNTFByZXByb2Nlc3NvckNvbnRleHQgfSBmcm9tIFwic2FwL2ZlL2NvcmUvVGVtcGxhdGVDb21wb25lbnRcIjtcbmltcG9ydCBDb21wb25lbnQgZnJvbSBcInNhcC91aS9jb3JlL0NvbXBvbmVudFwiO1xuaW1wb3J0IERlbGVnYXRlTWVkaWF0b3JBUEkgZnJvbSBcInNhcC91aS9mbC9hcHBseS9hcGkvRGVsZWdhdGVNZWRpYXRvckFQSVwiO1xuXG4vKipcbiAqIFJ1bnMgdGhlIHByb3ZpZGVkIGZyYWdtZW50IHRocm91Z2ggdGhlIHRlbXBsYXRpbmcgZW5naW5lIGlmIHRoZSBhcHAgY29tcG9uZW50IGlzIGFuIGluc3RhbmNlIG9mIHNhcC5mZS5jb3JlLkFwcENvbXBvbmVudFxuICogVGhpcyB3aWxsIGVuc3VyZSB0aGF0IGFsbCBpbmNsdWRlZCBidWlsZGluZyBibG9ja3Mgd2lsbCBiZSByZXNvbHZlZCB0byB0aGVpciB0YXJnZXQgY29udHJvbHMuXG4gKiBAcGFyYW0gZnJhZ21lbnQgVGhlIFhNTCBmcmFnbWVudCB0byBiZSBwcm9jZXNzZWRcbiAqIEBwYXJhbSBwcm9wZXJ0eUJhZyBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgYXBwIGNvbXBvbmVudCwgbW9kaWZpZXIsIHZpZXcsIGFuZCBvcHRpb25hbGx5IGNvbXBvbmVudElkXG4gKiBAcGFyYW0gcHJvcGVydHlCYWcuYXBwQ29tcG9uZW50XG4gKiBAcGFyYW0gcHJvcGVydHlCYWcubW9kaWZpZXJcbiAqIEBwYXJhbSBwcm9wZXJ0eUJhZy52aWV3XG4gKiBAcGFyYW0gcHJvcGVydHlCYWcuY29tcG9uZW50SWRcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcm9jZXNzZWQgWE1MIGZyYWdtZW50IGFzIGEgc3RyaW5nXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1blRlbXBsYXRpbmcoXG5cdGZyYWdtZW50OiBzdHJpbmcsXG5cdHByb3BlcnR5QmFnOiB7IGFwcENvbXBvbmVudDogQXBwQ29tcG9uZW50OyBtb2RpZmllcjogQmFzZVRyZWVNb2RpZmllcjsgdmlldzogRkVWaWV3OyBjb21wb25lbnRJZD86IHN0cmluZyB9XG4pOiBQcm9taXNlPHN0cmluZz4ge1xuXHR0cnkge1xuXHRcdGlmIChwcm9wZXJ0eUJhZy5hcHBDb21wb25lbnQuaXNBKFwic2FwLmZlLmNvcmUuQXBwQ29tcG9uZW50XCIpKSB7XG5cdFx0XHRjb25zdCB0ZW1wbGF0ZUNvbXBvbmVudCA9IChcblx0XHRcdFx0cHJvcGVydHlCYWcuY29tcG9uZW50SWRcblx0XHRcdFx0XHQ/IENvbXBvbmVudC5nZXRDb21wb25lbnRCeUlkKHByb3BlcnR5QmFnLmNvbXBvbmVudElkKVxuXHRcdFx0XHRcdDogQ29tcG9uZW50LmdldE93bmVyQ29tcG9uZW50Rm9yKHByb3BlcnR5QmFnLnZpZXcpXG5cdFx0XHQpIGFzIFRlbXBsYXRlQ29tcG9uZW50IHwgdW5kZWZpbmVkO1xuXHRcdFx0Y29uc3QgcHJlcHJvY2Vzc29yQ29udGV4dCA9ICh0ZW1wbGF0ZUNvbXBvbmVudD8ucHJlcHJvY2Vzc29yQ29udGV4dCA/PyB7fSkgYXMgWE1MUHJlcHJvY2Vzc29yQ29udGV4dDtcblx0XHRcdGNvbnN0IGZyYWdtZW50WE1MID0gbmV3IERPTVBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyhmcmFnbWVudCwgXCJ0ZXh0L3htbFwiKTtcblx0XHRcdGNvbnN0IHRlbXBsYXRlZFJlc3VsdCA9IGF3YWl0IENvbW1vblV0aWxzLnRlbXBsYXRlQ29udHJvbEZyYWdtZW50KFxuXHRcdFx0XHRmcmFnbWVudFhNTC5maXJzdEVsZW1lbnRDaGlsZCxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG1vZGVsczogcHJlcHJvY2Vzc29yQ29udGV4dC5tb2RlbHMsXG5cdFx0XHRcdFx0YmluZGluZ0NvbnRleHRzOiBwcmVwcm9jZXNzb3JDb250ZXh0LmJpbmRpbmdDb250ZXh0c1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR7IHZpZXc6IHByb3BlcnR5QmFnLnZpZXcsIGlzWE1MOiB0cnVlIH0sXG5cdFx0XHRcdHByb3BlcnR5QmFnLm1vZGlmaWVyXG5cdFx0XHQpO1xuXHRcdFx0aWYgKHRlbXBsYXRlZFJlc3VsdCBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcblx0XHRcdFx0YWRkR2VuZXJhdGVkSWRzVG9Db250cm9scyh0ZW1wbGF0ZWRSZXN1bHQpO1xuXHRcdFx0XHRyZXR1cm4gdGVtcGxhdGVkUmVzdWx0Lm91dGVySFRNTDtcblx0XHRcdH1cblx0XHRcdC8vIElmIHNvbWV0aGluZyBnb2VzIHdyb25nLCBmYWxsYmFjayB0byB0aGUgb3JpZ2luYWwgZnJhZ21lbnRcblx0XHRcdHJldHVybiBmcmFnbWVudDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZyYWdtZW50O1xuXHRcdH1cblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRMb2cuZXJyb3IoXCJFcnJvciBkdXJpbmcgRmlvcmkgRWxlbWVudHMgWE1MIFRlbXBsYXRpbmcgaW4gZmxleGliaWxpdHkgaGFuZGxlcjpcIiwgZXJyb3IgYXMgRXJyb3IpO1xuXHRcdHJldHVybiBmcmFnbWVudDtcblx0fVxufVxuXG4vLyBSZWdpc3RlciBhIGhvb2sgb250byB0aGUgYWRkWE1MIGhhbmRsZXIgZnJvbSBGbGV4IHRoYXQgd2lsbCBydW4gdGhlIHRlbXBsYXRpbmcgaWYgdGhlIGNvbmRpdGlvbnMgYXJlIHJpZ2h0XG5EZWxlZ2F0ZU1lZGlhdG9yQVBJLnJlZ2lzdGVyQWRkWE1MQWRqdXN0RnJhZ21lbnRIYW5kbGVyKHtcblx0a2V5OiBcIkZFWE1MVGVtcGxhdGluZ1wiLFxuXHRoYW5kbGVyOiBydW5UZW1wbGF0aW5nLFxuXHRyZWZlcmVuY2U6IFwic2FwLmZlLm1hY3Jvcy5CYXNlQWRkWE1MQWRqdXN0RnJhZ21lbnRIYW5kbGVyXCJcbn0pO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztFQVdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDQSxlQUFlQSxhQUFhQSxDQUMzQkMsUUFBZ0IsRUFDaEJDLFdBQTJHLEVBQ3pGO0lBQ2xCLElBQUk7TUFDSCxJQUFJQSxXQUFXLENBQUNDLFlBQVksQ0FBQ0MsR0FBRyxDQUFDLDBCQUEwQixDQUFDLEVBQUU7UUFDN0QsTUFBTUMsaUJBQWlCLEdBQ3RCSCxXQUFXLENBQUNJLFdBQVcsR0FDcEJDLFNBQVMsQ0FBQ0MsZ0JBQWdCLENBQUNOLFdBQVcsQ0FBQ0ksV0FBVyxDQUFDLEdBQ25EQyxTQUFTLENBQUNFLG9CQUFvQixDQUFDUCxXQUFXLENBQUNRLElBQUksQ0FDakI7UUFDbEMsTUFBTUMsbUJBQW1CLEdBQUlOLGlCQUFpQixFQUFFTSxtQkFBbUIsSUFBSSxDQUFDLENBQTRCO1FBQ3BHLE1BQU1DLFdBQVcsR0FBRyxJQUFJQyxTQUFTLENBQUMsQ0FBQyxDQUFDQyxlQUFlLENBQUNiLFFBQVEsRUFBRSxVQUFVLENBQUM7UUFDekUsTUFBTWMsZUFBZSxHQUFHLE1BQU1DLFdBQVcsQ0FBQ0MsdUJBQXVCLENBQ2hFTCxXQUFXLENBQUNNLGlCQUFpQixFQUM3QjtVQUNDQyxNQUFNLEVBQUVSLG1CQUFtQixDQUFDUSxNQUFNO1VBQ2xDQyxlQUFlLEVBQUVULG1CQUFtQixDQUFDUztRQUN0QyxDQUFDLEVBQ0Q7VUFBRVYsSUFBSSxFQUFFUixXQUFXLENBQUNRLElBQUk7VUFBRVcsS0FBSyxFQUFFO1FBQUssQ0FBQyxFQUN2Q25CLFdBQVcsQ0FBQ29CLFFBQ2IsQ0FBQztRQUNELElBQUlQLGVBQWUsWUFBWVEsT0FBTyxFQUFFO1VBQ3ZDQyx5QkFBeUIsQ0FBQ1QsZUFBZSxDQUFDO1VBQzFDLE9BQU9BLGVBQWUsQ0FBQ1UsU0FBUztRQUNqQztRQUNBO1FBQ0EsT0FBT3hCLFFBQVE7TUFDaEIsQ0FBQyxNQUFNO1FBQ04sT0FBT0EsUUFBUTtNQUNoQjtJQUNELENBQUMsQ0FBQyxPQUFPeUIsS0FBSyxFQUFFO01BQ2ZDLEdBQUcsQ0FBQ0QsS0FBSyxDQUFDLG9FQUFvRSxFQUFFQSxLQUFjLENBQUM7TUFDL0YsT0FBT3pCLFFBQVE7SUFDaEI7RUFDRDs7RUFFQTtFQUNBMkIsbUJBQW1CLENBQUNDLG1DQUFtQyxDQUFDO0lBQ3ZEQyxHQUFHLEVBQUUsaUJBQWlCO0lBQ3RCQyxPQUFPLEVBQUUvQixhQUFhO0lBQ3RCZ0MsU0FBUyxFQUFFO0VBQ1osQ0FBQyxDQUFDO0FBQUMiLCJpZ25vcmVMaXN0IjpbXX0=
@@ -0,0 +1,65 @@
1
+ import Log from "sap/base/Log";
2
+ import type AppComponent from "sap/fe/core/AppComponent";
3
+ import type { FEView } from "sap/fe/core/BaseController";
4
+ import type { BaseTreeModifier } from "sap/fe/core/CommonUtils";
5
+ import CommonUtils from "sap/fe/core/CommonUtils";
6
+ import { addGeneratedIdsToControls } from "sap/fe/core/flexibility/XMLTools";
7
+ import type TemplateComponent from "sap/fe/core/TemplateComponent";
8
+ import type { XMLPreprocessorContext } from "sap/fe/core/TemplateComponent";
9
+ import Component from "sap/ui/core/Component";
10
+ import DelegateMediatorAPI from "sap/ui/fl/apply/api/DelegateMediatorAPI";
11
+
12
+ /**
13
+ * Runs the provided fragment through the templating engine if the app component is an instance of sap.fe.core.AppComponent
14
+ * This will ensure that all included building blocks will be resolved to their target controls.
15
+ * @param fragment The XML fragment to be processed
16
+ * @param propertyBag An object containing the app component, modifier, view, and optionally componentId
17
+ * @param propertyBag.appComponent
18
+ * @param propertyBag.modifier
19
+ * @param propertyBag.view
20
+ * @param propertyBag.componentId
21
+ * @returns A promise that resolves to the processed XML fragment as a string
22
+ */
23
+ async function runTemplating(
24
+ fragment: string,
25
+ propertyBag: { appComponent: AppComponent; modifier: BaseTreeModifier; view: FEView; componentId?: string }
26
+ ): Promise<string> {
27
+ try {
28
+ if (propertyBag.appComponent.isA("sap.fe.core.AppComponent")) {
29
+ const templateComponent = (
30
+ propertyBag.componentId
31
+ ? Component.getComponentById(propertyBag.componentId)
32
+ : Component.getOwnerComponentFor(propertyBag.view)
33
+ ) as TemplateComponent | undefined;
34
+ const preprocessorContext = (templateComponent?.preprocessorContext ?? {}) as XMLPreprocessorContext;
35
+ const fragmentXML = new DOMParser().parseFromString(fragment, "text/xml");
36
+ const templatedResult = await CommonUtils.templateControlFragment(
37
+ fragmentXML.firstElementChild,
38
+ {
39
+ models: preprocessorContext.models,
40
+ bindingContexts: preprocessorContext.bindingContexts
41
+ },
42
+ { view: propertyBag.view, isXML: true },
43
+ propertyBag.modifier
44
+ );
45
+ if (templatedResult instanceof Element) {
46
+ addGeneratedIdsToControls(templatedResult);
47
+ return templatedResult.outerHTML;
48
+ }
49
+ // If something goes wrong, fallback to the original fragment
50
+ return fragment;
51
+ } else {
52
+ return fragment;
53
+ }
54
+ } catch (error) {
55
+ Log.error("Error during Fiori Elements XML Templating in flexibility handler:", error as Error);
56
+ return fragment;
57
+ }
58
+ }
59
+
60
+ // Register a hook onto the addXML handler from Flex that will run the templating if the conditions are right
61
+ DelegateMediatorAPI.registerAddXMLAdjustFragmentHandler({
62
+ key: "FEXMLTemplating",
63
+ handler: runTemplating,
64
+ reference: "sap.fe.macros.BaseAddXMLAdjustFragmentHandler"
65
+ });
@@ -0,0 +1,71 @@
1
+ /*!
2
+ * SAP UI development toolkit for HTML5 (SAPUI5)
3
+ * (c) Copyright 2009-2025 SAP SE. All rights reserved
4
+ */
5
+ sap.ui.define([], function () {
6
+ "use strict";
7
+
8
+ var _exports = {};
9
+ /**
10
+ * Traverses a DOM element and adds generated ID properties to nodes representing controls that are missing IDs.
11
+ * Controls are identified by local names starting with an uppercase letter.
12
+ * @param element The root DOM element to traverse
13
+ * @param prefix Optional prefix for generated IDs
14
+ * @returns The number of IDs that were generated and added
15
+ */
16
+ function addGeneratedIdsToControls(element) {
17
+ let prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "generatedId";
18
+ let idCounter = 0;
19
+ const generatedIds = new Set();
20
+
21
+ /**
22
+ * Recursively traverses the DOM tree and processes each element.
23
+ * @param node The current element being processed
24
+ */
25
+ function traverse(node) {
26
+ // Check if this is a control (local name starts with uppercase) and missing an ID
27
+ if (isControl(node) && !node.hasAttribute("id")) {
28
+ const generatedId = generateUniqueId(prefix, generatedIds);
29
+ node.setAttribute("id", generatedId);
30
+ generatedIds.add(generatedId);
31
+ idCounter++;
32
+ }
33
+
34
+ // Recursively process all child elements
35
+ for (let i = 0; i < node.children.length; i++) {
36
+ traverse(node.children[i]);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Determines if an element represents a UI5 control based on its local name.
42
+ * @param controlElement The element to check
43
+ * @returns True if the element represents a control
44
+ */
45
+ function isControl(controlElement) {
46
+ const localName = controlElement.localName ?? controlElement.tagName.toLowerCase();
47
+ return localName.length > 0 && localName.charAt(0) === localName.charAt(0).toUpperCase();
48
+ }
49
+
50
+ /**
51
+ * Generates a unique ID that doesn't conflict with existing IDs.
52
+ * @param basePrefix The base prefix for the ID
53
+ * @param existingIds Set of already generated IDs
54
+ * @returns A unique ID string
55
+ */
56
+ function generateUniqueId(basePrefix, existingIds) {
57
+ let counter = 1;
58
+ let candidateId = `${basePrefix}_${counter}`;
59
+ while (existingIds.has(candidateId) || document.getElementById(candidateId)) {
60
+ counter++;
61
+ candidateId = `${basePrefix}_${counter}`;
62
+ }
63
+ return candidateId;
64
+ }
65
+ traverse(element);
66
+ return idCounter;
67
+ }
68
+ _exports.addGeneratedIdsToControls = addGeneratedIdsToControls;
69
+ return _exports;
70
+ }, false);
71
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhZGRHZW5lcmF0ZWRJZHNUb0NvbnRyb2xzIiwiZWxlbWVudCIsInByZWZpeCIsImFyZ3VtZW50cyIsImxlbmd0aCIsInVuZGVmaW5lZCIsImlkQ291bnRlciIsImdlbmVyYXRlZElkcyIsIlNldCIsInRyYXZlcnNlIiwibm9kZSIsImlzQ29udHJvbCIsImhhc0F0dHJpYnV0ZSIsImdlbmVyYXRlZElkIiwiZ2VuZXJhdGVVbmlxdWVJZCIsInNldEF0dHJpYnV0ZSIsImFkZCIsImkiLCJjaGlsZHJlbiIsImNvbnRyb2xFbGVtZW50IiwibG9jYWxOYW1lIiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiY2hhckF0IiwidG9VcHBlckNhc2UiLCJiYXNlUHJlZml4IiwiZXhpc3RpbmdJZHMiLCJjb3VudGVyIiwiY2FuZGlkYXRlSWQiLCJoYXMiLCJkb2N1bWVudCIsImdldEVsZW1lbnRCeUlkIiwiX2V4cG9ydHMiXSwic291cmNlUm9vdCI6Ii4iLCJzb3VyY2VzIjpbIlhNTFRvb2xzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVHJhdmVyc2VzIGEgRE9NIGVsZW1lbnQgYW5kIGFkZHMgZ2VuZXJhdGVkIElEIHByb3BlcnRpZXMgdG8gbm9kZXMgcmVwcmVzZW50aW5nIGNvbnRyb2xzIHRoYXQgYXJlIG1pc3NpbmcgSURzLlxuICogQ29udHJvbHMgYXJlIGlkZW50aWZpZWQgYnkgbG9jYWwgbmFtZXMgc3RhcnRpbmcgd2l0aCBhbiB1cHBlcmNhc2UgbGV0dGVyLlxuICogQHBhcmFtIGVsZW1lbnQgVGhlIHJvb3QgRE9NIGVsZW1lbnQgdG8gdHJhdmVyc2VcbiAqIEBwYXJhbSBwcmVmaXggT3B0aW9uYWwgcHJlZml4IGZvciBnZW5lcmF0ZWQgSURzXG4gKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIElEcyB0aGF0IHdlcmUgZ2VuZXJhdGVkIGFuZCBhZGRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkR2VuZXJhdGVkSWRzVG9Db250cm9scyhlbGVtZW50OiBFbGVtZW50LCBwcmVmaXggPSBcImdlbmVyYXRlZElkXCIpOiBudW1iZXIge1xuXHRsZXQgaWRDb3VudGVyID0gMDtcblx0Y29uc3QgZ2VuZXJhdGVkSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cblx0LyoqXG5cdCAqIFJlY3Vyc2l2ZWx5IHRyYXZlcnNlcyB0aGUgRE9NIHRyZWUgYW5kIHByb2Nlc3NlcyBlYWNoIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBjdXJyZW50IGVsZW1lbnQgYmVpbmcgcHJvY2Vzc2VkXG5cdCAqL1xuXHRmdW5jdGlvbiB0cmF2ZXJzZShub2RlOiBFbGVtZW50KTogdm9pZCB7XG5cdFx0Ly8gQ2hlY2sgaWYgdGhpcyBpcyBhIGNvbnRyb2wgKGxvY2FsIG5hbWUgc3RhcnRzIHdpdGggdXBwZXJjYXNlKSBhbmQgbWlzc2luZyBhbiBJRFxuXHRcdGlmIChpc0NvbnRyb2wobm9kZSkgJiYgIW5vZGUuaGFzQXR0cmlidXRlKFwiaWRcIikpIHtcblx0XHRcdGNvbnN0IGdlbmVyYXRlZElkID0gZ2VuZXJhdGVVbmlxdWVJZChwcmVmaXgsIGdlbmVyYXRlZElkcyk7XG5cdFx0XHRub2RlLnNldEF0dHJpYnV0ZShcImlkXCIsIGdlbmVyYXRlZElkKTtcblx0XHRcdGdlbmVyYXRlZElkcy5hZGQoZ2VuZXJhdGVkSWQpO1xuXHRcdFx0aWRDb3VudGVyKys7XG5cdFx0fVxuXG5cdFx0Ly8gUmVjdXJzaXZlbHkgcHJvY2VzcyBhbGwgY2hpbGQgZWxlbWVudHNcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRyYXZlcnNlKG5vZGUuY2hpbGRyZW5baV0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEZXRlcm1pbmVzIGlmIGFuIGVsZW1lbnQgcmVwcmVzZW50cyBhIFVJNSBjb250cm9sIGJhc2VkIG9uIGl0cyBsb2NhbCBuYW1lLlxuXHQgKiBAcGFyYW0gY29udHJvbEVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gY2hlY2tcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgZWxlbWVudCByZXByZXNlbnRzIGEgY29udHJvbFxuXHQgKi9cblx0ZnVuY3Rpb24gaXNDb250cm9sKGNvbnRyb2xFbGVtZW50OiBFbGVtZW50KTogYm9vbGVhbiB7XG5cdFx0Y29uc3QgbG9jYWxOYW1lID0gY29udHJvbEVsZW1lbnQubG9jYWxOYW1lID8/IGNvbnRyb2xFbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRyZXR1cm4gbG9jYWxOYW1lLmxlbmd0aCA+IDAgJiYgbG9jYWxOYW1lLmNoYXJBdCgwKSA9PT0gbG9jYWxOYW1lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBJRCB0aGF0IGRvZXNuJ3QgY29uZmxpY3Qgd2l0aCBleGlzdGluZyBJRHMuXG5cdCAqIEBwYXJhbSBiYXNlUHJlZml4IFRoZSBiYXNlIHByZWZpeCBmb3IgdGhlIElEXG5cdCAqIEBwYXJhbSBleGlzdGluZ0lkcyBTZXQgb2YgYWxyZWFkeSBnZW5lcmF0ZWQgSURzXG5cdCAqIEByZXR1cm5zIEEgdW5pcXVlIElEIHN0cmluZ1xuXHQgKi9cblx0ZnVuY3Rpb24gZ2VuZXJhdGVVbmlxdWVJZChiYXNlUHJlZml4OiBzdHJpbmcsIGV4aXN0aW5nSWRzOiBTZXQ8c3RyaW5nPik6IHN0cmluZyB7XG5cdFx0bGV0IGNvdW50ZXIgPSAxO1xuXHRcdGxldCBjYW5kaWRhdGVJZCA9IGAke2Jhc2VQcmVmaXh9XyR7Y291bnRlcn1gO1xuXG5cdFx0d2hpbGUgKGV4aXN0aW5nSWRzLmhhcyhjYW5kaWRhdGVJZCkgfHwgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY2FuZGlkYXRlSWQpKSB7XG5cdFx0XHRjb3VudGVyKys7XG5cdFx0XHRjYW5kaWRhdGVJZCA9IGAke2Jhc2VQcmVmaXh9XyR7Y291bnRlcn1gO1xuXHRcdH1cblxuXHRcdHJldHVybiBjYW5kaWRhdGVJZDtcblx0fVxuXG5cdHRy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
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Traverses a DOM element and adds generated ID properties to nodes representing controls that are missing IDs.
3
+ * Controls are identified by local names starting with an uppercase letter.
4
+ * @param element The root DOM element to traverse
5
+ * @param prefix Optional prefix for generated IDs
6
+ * @returns The number of IDs that were generated and added
7
+ */
8
+ export function addGeneratedIdsToControls(element: Element, prefix = "generatedId"): number {
9
+ let idCounter = 0;
10
+ const generatedIds = new Set<string>();
11
+
12
+ /**
13
+ * Recursively traverses the DOM tree and processes each element.
14
+ * @param node The current element being processed
15
+ */
16
+ function traverse(node: Element): void {
17
+ // Check if this is a control (local name starts with uppercase) and missing an ID
18
+ if (isControl(node) && !node.hasAttribute("id")) {
19
+ const generatedId = generateUniqueId(prefix, generatedIds);
20
+ node.setAttribute("id", generatedId);
21
+ generatedIds.add(generatedId);
22
+ idCounter++;
23
+ }
24
+
25
+ // Recursively process all child elements
26
+ for (let i = 0; i < node.children.length; i++) {
27
+ traverse(node.children[i]);
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Determines if an element represents a UI5 control based on its local name.
33
+ * @param controlElement The element to check
34
+ * @returns True if the element represents a control
35
+ */
36
+ function isControl(controlElement: Element): boolean {
37
+ const localName = controlElement.localName ?? controlElement.tagName.toLowerCase();
38
+ return localName.length > 0 && localName.charAt(0) === localName.charAt(0).toUpperCase();
39
+ }
40
+
41
+ /**
42
+ * Generates a unique ID that doesn't conflict with existing IDs.
43
+ * @param basePrefix The base prefix for the ID
44
+ * @param existingIds Set of already generated IDs
45
+ * @returns A unique ID string
46
+ */
47
+ function generateUniqueId(basePrefix: string, existingIds: Set<string>): string {
48
+ let counter = 1;
49
+ let candidateId = `${basePrefix}_${counter}`;
50
+
51
+ while (existingIds.has(candidateId) || document.getElementById(candidateId)) {
52
+ counter++;
53
+ candidateId = `${basePrefix}_${counter}`;
54
+ }
55
+
56
+ return candidateId;
57
+ }
58
+
59
+ traverse(element);
60
+ return idCounter;
61
+ }
@@ -1,10 +1,10 @@
1
1
  {
2
- "_version": "1.14.0",
2
+ "_version": "2.0.0",
3
3
  "sap.app": {
4
4
  "id": "sap.fe.core.fpm",
5
5
  "type": "component",
6
6
  "applicationVersion": {
7
- "version": "1.141.2"
7
+ "version": "1.143.0"
8
8
  },
9
9
  "title": "Object Page",
10
10
  "tags": {