@sap-ux/fe-fpm-writer 0.40.12 → 0.41.1

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.
@@ -1,32 +1,6 @@
1
1
  import type { Editor } from 'mem-fs-editor';
2
- import { BuildingBlockType, type BuildingBlock, type BuildingBlockConfig, type EmbededFragment } from './types';
3
- import type { InternalCustomElement } from '../common/types';
2
+ import { type BuildingBlock, type BuildingBlockConfig } from './types';
4
3
  import { type CodeSnippet } from '../prompts/types';
5
- /**
6
- * Type for embedded fragment data used in building block processing.
7
- */
8
- type EmbeddedFragmentData = InternalCustomElement & EmbededFragment;
9
- /**
10
- * Configuration for building block templates.
11
- */
12
- interface BuildingBlockTemplateConfig {
13
- nodes: {
14
- explicit: string;
15
- default: string;
16
- };
17
- templateType: string;
18
- templateFile: string;
19
- namespace: {
20
- uri: string;
21
- prefix: string;
22
- };
23
- resultPropertyName: string;
24
- processor: (buildingBlockData: BuildingBlock, fs: Editor, viewPath: string, config: BuildingBlockTemplateConfig, embededFragment?: EmbeddedFragmentData) => void;
25
- }
26
- /**
27
- * Configuration map for building block types.
28
- */
29
- export declare const BUILDING_BLOCK_CONFIG: Partial<Record<BuildingBlockType, BuildingBlockTemplateConfig>>;
30
4
  /**
31
5
  * Generates a building block into the provided xml view file.
32
6
  *
@@ -55,5 +29,4 @@ export declare function getManifestContent(fs: Editor, library?: string): Promis
55
29
  export declare function getSerializedFileContent<T extends BuildingBlock>(basePath: string, config: BuildingBlockConfig<T>, fs?: Editor): Promise<{
56
30
  [questionName: string]: CodeSnippet;
57
31
  }>;
58
- export {};
59
32
  //# sourceMappingURL=index.d.ts.map
@@ -36,7 +36,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.BUILDING_BLOCK_CONFIG = void 0;
40
39
  exports.generateBuildingBlock = generateBuildingBlock;
41
40
  exports.getManifestContent = getManifestContent;
42
41
  exports.getSerializedFileContent = getSerializedFileContent;
@@ -53,38 +52,16 @@ const types_1 = require("./types");
53
52
  const validate_1 = require("../common/validate");
54
53
  const templates_1 = require("../templates");
55
54
  const types_2 = require("../prompts/types");
56
- const event_handler_1 = require("../common/event-handler");
57
55
  const file_1 = require("../common/file");
58
56
  const utils_1 = require("../common/utils");
59
- const defaults_1 = require("../common/defaults");
60
57
  const xml_1 = require("./prompts/utils/xml");
61
58
  const i18n_1 = require("../i18n");
59
+ const processor_1 = require("./processor");
62
60
  const PLACEHOLDERS = {
63
61
  'id': 'REPLACE_WITH_BUILDING_BLOCK_ID',
64
62
  'entitySet': 'REPLACE_WITH_ENTITY',
65
63
  'qualifier': 'REPLACE_WITH_A_QUALIFIER'
66
64
  };
67
- /**
68
- * Configuration map for building block types.
69
- */
70
- exports.BUILDING_BLOCK_CONFIG = {
71
- [types_1.BuildingBlockType.CustomColumn]: {
72
- nodes: { explicit: 'columns', default: 'Column' },
73
- templateType: 'common',
74
- templateFile: 'common/Fragment.xml',
75
- namespace: { uri: 'sap.fe.macros.table', prefix: 'macrosTable' },
76
- resultPropertyName: 'hasTableColumns',
77
- processor: processCustomColumn
78
- },
79
- [types_1.BuildingBlockType.CustomFilterField]: {
80
- nodes: { explicit: 'filterFields', default: 'FilterField' },
81
- templateType: 'filter',
82
- templateFile: 'filter/fragment.xml',
83
- namespace: { uri: 'sap.fe.macros.filterBar', prefix: 'macros' },
84
- resultPropertyName: 'hasFilterFields',
85
- processor: processCustomFilterField
86
- }
87
- };
88
65
  /**
89
66
  * Generates a building block into the provided xml view file.
90
67
  *
@@ -106,13 +83,14 @@ async function generateBuildingBlock(basePath, config, fs) {
106
83
  const { path: manifestPath, content: manifest } = await (0, utils_1.getManifest)(basePath, fs);
107
84
  // Read the view xml and template files and update contents of the view xml file
108
85
  const xmlDocument = getUI5XmlDocument(basePath, viewOrFragmentPath, fs);
109
- const { updatedAggregationPath, processedBuildingBlockData, hasAggregation, aggregationNamespace } = processBuildingBlock(buildingBlockData, xmlDocument, manifestPath, manifest, aggregationPath, fs);
86
+ const { updatedAggregationPath, processedBuildingBlockData, hasAggregation, aggregationNamespace } = (0, processor_1.processBuildingBlock)(buildingBlockData, xmlDocument, manifestPath, manifest, aggregationPath, fs);
110
87
  const templateConfig = {
111
88
  hasAggregation,
112
89
  aggregationNamespace
113
90
  };
114
91
  const templateDocument = getTemplateDocument(processedBuildingBlockData, xmlDocument, fs, manifest, templateConfig);
115
- if (buildingBlockData.buildingBlockType === types_1.BuildingBlockType.RichTextEditor) {
92
+ if (buildingBlockData.buildingBlockType === types_1.BuildingBlockType.RichTextEditor ||
93
+ buildingBlockData.buildingBlockType === types_1.BuildingBlockType.RichTextEditorButtonGroups) {
116
94
  const minUI5Version = manifest ? (0, semver_1.coerce)((0, project_access_1.getMinimumUI5Version)(manifest)) : undefined;
117
95
  if (minUI5Version && (0, semver_1.lt)(minUI5Version, '1.117.0')) {
118
96
  const t = (0, i18n_1.translate)(i18n_1.i18nNamespaces.buildingBlock, 'richTextEditorBuildingBlock.');
@@ -135,177 +113,6 @@ async function generateBuildingBlock(basePath, config, fs) {
135
113
  }
136
114
  return fs;
137
115
  }
138
- /**
139
- * Updates aggregation path based on XML document structure.
140
- *
141
- * @param {Document} xmlDocument - The XML document to analyze
142
- * @param {string} aggregationPath - The current aggregation path
143
- * @param {CustomColumn | CustomFilterField} buildingBlockData - The building block data with embedded fragment
144
- * @param {AggregationConfig} config - Configuration specifying aggregation and element names
145
- * @returns {object} Object containing the updated aggregation path
146
- */
147
- function updateAggregationPath(xmlDocument, aggregationPath, buildingBlockData, config) {
148
- if (!buildingBlockData.embededFragment) {
149
- return { updatedAggregationPath: aggregationPath, hasElement: false };
150
- }
151
- const xpathSelect = xpath.useNamespaces(xmlDocument.firstChild._nsMap);
152
- // First, get the target element from the aggregationPath
153
- const targetElement = xpathSelect(aggregationPath, xmlDocument);
154
- if (!targetElement || !Array.isArray(targetElement) || targetElement.length === 0) {
155
- return { updatedAggregationPath: aggregationPath, hasElement: false };
156
- }
157
- const targetNode = targetElement[0];
158
- // Check if the explicit aggregation exists within the specific target element
159
- const hasAggregation = xpathSelect(`./*[local-name()='${config.aggregationName}']`, targetNode);
160
- if (hasAggregation && Array.isArray(hasAggregation) && hasAggregation.length > 0) {
161
- return {
162
- updatedAggregationPath: aggregationPath + `/${(0, xml_1.getOrAddNamespace)(xmlDocument)}:${config.aggregationName}`,
163
- hasElement: true
164
- };
165
- }
166
- else {
167
- // Check if the default aggregation element exists within the specific target element
168
- const useDefaultAggregation = xpathSelect(`./*[local-name()='${config.elementName}']`, targetNode);
169
- if (useDefaultAggregation && Array.isArray(useDefaultAggregation) && useDefaultAggregation.length > 0) {
170
- return { updatedAggregationPath: aggregationPath, hasElement: true };
171
- }
172
- }
173
- return { updatedAggregationPath: aggregationPath, hasElement: false };
174
- }
175
- /**
176
- * Processes building block configuration.
177
- *
178
- * @param {BuildingBlock} buildingBlockData - The building block data
179
- * @param {Document} xmlDocument - The XML document
180
- * @param {string} manifestPath - The manifest file path
181
- * @param {Manifest} manifest - The manifest object
182
- * @param {string} aggregationPath - The aggregation path
183
- * @param {Editor} fs - The memfs editor instance
184
- * @returns {object} Object containing updated aggregation path and processed building block data
185
- */
186
- function processBuildingBlock(buildingBlockData, xmlDocument, manifestPath, manifest, aggregationPath, fs) {
187
- let updatedAggregationPath = aggregationPath;
188
- let hasAggregation = false;
189
- let aggregationNamespace = 'macrosTable';
190
- let embededFragment;
191
- let viewPath;
192
- // Get configuration for the building block type
193
- const config = exports.BUILDING_BLOCK_CONFIG[buildingBlockData.buildingBlockType];
194
- if (!config) {
195
- // Return defaults if no configuration is found
196
- return {
197
- updatedAggregationPath,
198
- processedBuildingBlockData: buildingBlockData,
199
- hasAggregation,
200
- aggregationNamespace
201
- };
202
- }
203
- // Process embedded fragment for types that support it
204
- if ((isCustomColumn(buildingBlockData) || isCustomFilterField(buildingBlockData)) &&
205
- buildingBlockData.embededFragment) {
206
- embededFragment = (0, defaults_1.setCommonDefaults)(buildingBlockData.embededFragment, manifestPath, manifest);
207
- viewPath = (0, node_path_1.join)(embededFragment.path, `${embededFragment.fragmentFile ?? embededFragment.name}.fragment.xml`);
208
- // Use the processor function from the configuration
209
- config.processor(buildingBlockData, fs, viewPath, config, embededFragment);
210
- const result = updateAggregationPath(xmlDocument, aggregationPath, buildingBlockData, {
211
- aggregationName: config.nodes.explicit,
212
- elementName: config.nodes.default,
213
- resultPropertyName: config.resultPropertyName
214
- });
215
- updatedAggregationPath = result.updatedAggregationPath;
216
- hasAggregation = result.hasElement;
217
- aggregationNamespace = (0, xml_1.getOrAddNamespace)(xmlDocument, config.namespace.uri, config.namespace.prefix);
218
- }
219
- return {
220
- updatedAggregationPath,
221
- processedBuildingBlockData: buildingBlockData,
222
- hasAggregation,
223
- aggregationNamespace
224
- };
225
- }
226
- /**
227
- * Processes custom column building block.
228
- *
229
- * @param {BuildingBlock} buildingBlockData - The building block data
230
- * @param {Editor} fs - The memfs editor instance
231
- * @param {string} viewPath - The view path
232
- * @param {BuildingBlockTemplateConfig} config - The building block configuration
233
- */
234
- function processCustomColumn(buildingBlockData, fs, viewPath, config) {
235
- if (!isCustomColumn(buildingBlockData)) {
236
- throw new Error('Expected CustomColumn building block data');
237
- }
238
- const columnConfig = buildingBlockData.embededFragment;
239
- let processedEventHandler;
240
- // Apply event handler
241
- if (columnConfig.eventHandler) {
242
- processedEventHandler = (0, event_handler_1.applyEventHandlerConfiguration)(fs, columnConfig, columnConfig.eventHandler, {
243
- controllerSuffix: false,
244
- typescript: columnConfig.typescript
245
- });
246
- columnConfig.eventHandler = processedEventHandler;
247
- }
248
- columnConfig.content = (0, defaults_1.getDefaultFragmentContent)('Sample Text', processedEventHandler);
249
- if (!fs.exists(viewPath)) {
250
- (0, file_1.copyTpl)(fs, (0, templates_1.getTemplatePath)(config.templateFile), viewPath, columnConfig);
251
- }
252
- }
253
- /**
254
- * Processes custom filter field building block.
255
- *
256
- * @param {BuildingBlock} buildingBlockData - The building block data
257
- * @param {Editor} fs - The memfs editor instance
258
- * @param {string} viewPath - The view path
259
- * @param {BuildingBlockTemplateConfig} config - The building block configuration
260
- * @param {EmbeddedFragmentData} embededFragment - The embedded fragment data
261
- */
262
- function processCustomFilterField(buildingBlockData, fs, viewPath, config, embededFragment) {
263
- if (!isCustomFilterField(buildingBlockData)) {
264
- throw new Error('Expected CustomFilterField building block data');
265
- }
266
- if (!embededFragment) {
267
- throw new Error('EmbeddedFragment is required for CustomFilterField');
268
- }
269
- const filterConfig = {
270
- label: buildingBlockData.label,
271
- property: buildingBlockData.property,
272
- required: buildingBlockData.required ?? false,
273
- position: buildingBlockData.position,
274
- eventHandler: buildingBlockData.embededFragment?.eventHandler,
275
- ns: embededFragment.ns,
276
- name: embededFragment.name,
277
- path: embededFragment.path
278
- };
279
- // Apply event handler
280
- if (filterConfig.eventHandler) {
281
- filterConfig.eventHandler = (0, event_handler_1.applyEventHandlerConfiguration)(fs, filterConfig, filterConfig.eventHandler, {
282
- controllerSuffix: false,
283
- typescript: buildingBlockData.embededFragment?.typescript,
284
- templatePath: 'filter/Controller'
285
- });
286
- }
287
- if (!fs.exists(viewPath)) {
288
- (0, file_1.copyTpl)(fs, (0, templates_1.getTemplatePath)(config.templateFile), viewPath, filterConfig);
289
- }
290
- }
291
- /**
292
- * Type guard to check if the building block data is a custom column.
293
- *
294
- * @param {BuildingBlock} data - The building block data to check
295
- * @returns {boolean} True if the data is a custom column
296
- */
297
- function isCustomColumn(data) {
298
- return data.buildingBlockType === types_1.BuildingBlockType.CustomColumn;
299
- }
300
- /**
301
- * Type guard to check if the building block data is a custom filter field.
302
- *
303
- * @param {BuildingBlock} data - The building block data to check
304
- * @returns {boolean} True if the data is a custom filter field
305
- */
306
- function isCustomFilterField(data) {
307
- return data.buildingBlockType === types_1.BuildingBlockType.CustomFilterField;
308
- }
309
116
  /**
310
117
  * Returns the UI5 xml file document (view/fragment).
311
118
  *
@@ -0,0 +1,67 @@
1
+ import type { Editor } from 'mem-fs-editor';
2
+ import { BuildingBlockType, type BuildingBlock, type EmbededFragment } from './types';
3
+ import type { Manifest, InternalCustomElement } from '../common/types';
4
+ /**
5
+ * Type for embedded fragment data used in building block processing.
6
+ */
7
+ type EmbeddedFragmentData = InternalCustomElement & EmbededFragment;
8
+ /**
9
+ * Namespace for XML elements.
10
+ */
11
+ interface NamespaceConfig {
12
+ uri: string;
13
+ prefix: string;
14
+ }
15
+ /**
16
+ * Context for processing building blocks.
17
+ */
18
+ interface ProcessingContext {
19
+ fs: Editor;
20
+ xmlDocument?: Document;
21
+ viewPath?: string;
22
+ embeddedFragment?: EmbeddedFragmentData;
23
+ updatedAggregationPath?: string;
24
+ hasAggregation?: boolean;
25
+ }
26
+ /**
27
+ * Configuration for building block templates.
28
+ */
29
+ interface BuildingBlockTemplateConfig {
30
+ aggregationConfig: {
31
+ aggregationName: string;
32
+ elementName: string;
33
+ };
34
+ templateFile?: string;
35
+ namespace: NamespaceConfig;
36
+ processor: (buildingBlockData: BuildingBlock, context: ProcessingContext) => void;
37
+ }
38
+ /**
39
+ * Button group configurations used for validation and providing available button groups.
40
+ */
41
+ export declare const BUTTON_GROUP_CONFIGS: {
42
+ name: string;
43
+ buttons: string;
44
+ }[];
45
+ /**
46
+ * Configuration map for building block types.
47
+ */
48
+ export declare const BUILDING_BLOCK_CONFIG: Partial<Record<BuildingBlockType, BuildingBlockTemplateConfig>>;
49
+ /**
50
+ * Processes building block configuration.
51
+ *
52
+ * @param {BuildingBlock} buildingBlockData - The building block data
53
+ * @param {Document} xmlDocument - The XML document
54
+ * @param {string} manifestPath - The manifest file path
55
+ * @param {Manifest} manifest - The manifest object
56
+ * @param {string} aggregationPath - The aggregation path
57
+ * @param {Editor} fs - The memfs editor instance
58
+ * @returns {object} Object containing updated aggregation path and processed building block data
59
+ */
60
+ export declare function processBuildingBlock<T extends BuildingBlock>(buildingBlockData: T, xmlDocument: Document, manifestPath: string, manifest: Manifest, aggregationPath: string, fs: Editor): {
61
+ updatedAggregationPath: string;
62
+ processedBuildingBlockData: T;
63
+ hasAggregation: boolean;
64
+ aggregationNamespace: string;
65
+ };
66
+ export {};
67
+ //# sourceMappingURL=processor.d.ts.map