@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.
- package/dist/building-block/index.d.ts +1 -28
- package/dist/building-block/index.js +4 -197
- package/dist/building-block/processor.d.ts +67 -0
- package/dist/building-block/processor.js +437 -0
- package/dist/building-block/prompts/questions/index.d.ts +1 -0
- package/dist/building-block/prompts/questions/index.js +1 -0
- package/dist/building-block/prompts/questions/richTextEditorButtonGroups.d.ts +12 -0
- package/dist/building-block/prompts/questions/richTextEditorButtonGroups.js +50 -0
- package/dist/building-block/prompts/utils/prompt-helpers.d.ts +15 -0
- package/dist/building-block/prompts/utils/prompt-helpers.js +33 -0
- package/dist/building-block/prompts/utils/xml.d.ts +9 -0
- package/dist/building-block/prompts/utils/xml.js +80 -0
- package/dist/building-block/types.d.ts +66 -1
- package/dist/building-block/types.js +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/prompts/api.js +1 -1
- package/dist/prompts/map.d.ts +6 -3
- package/dist/prompts/map.js +4 -1
- package/dist/prompts/translations/i18n.d.ts +20 -7
- package/dist/prompts/translations/i18n.js +21 -8
- package/dist/prompts/types.d.ts +2 -1
- package/dist/prompts/types.js +1 -0
- package/package.json +4 -4
- package/templates/building-block/rich-text-editor-button-groups/View.xml +20 -0
|
@@ -1,32 +1,6 @@
|
|
|
1
1
|
import type { Editor } from 'mem-fs-editor';
|
|
2
|
-
import {
|
|
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
|