@progress/kendo-angular-conversational-ui 20.0.0-develop.4 → 20.0.0-develop.6

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 (86) hide show
  1. package/chat/api/action.interface.d.ts +1 -1
  2. package/chat/api/attachment.interface.d.ts +1 -1
  3. package/chat/api/chat-file-interface.d.ts +41 -0
  4. package/chat/api/chat-suggestion.interface.d.ts +25 -0
  5. package/chat/api/file-action.d.ts +42 -0
  6. package/chat/api/file-download-event.interface.d.ts +21 -0
  7. package/chat/api/index.d.ts +8 -0
  8. package/chat/api/message-action.d.ts +42 -0
  9. package/{esm2022/chat/chat.directives.mjs → chat/api/message-toolbar-visibility.d.ts} +4 -4
  10. package/chat/api/message-width-mode.d.ts +10 -0
  11. package/chat/api/message.interface.d.ts +30 -12
  12. package/chat/api/send-button-settings.d.ts +15 -0
  13. package/chat/api/user.interface.d.ts +4 -0
  14. package/chat/attachment.component.d.ts +1 -1
  15. package/chat/cards/hero-card.component.d.ts +1 -1
  16. package/chat/chat-file.component.d.ts +34 -0
  17. package/chat/chat-item.d.ts +1 -0
  18. package/chat/chat-view.d.ts +1 -1
  19. package/chat/chat.component.d.ts +218 -19
  20. package/chat/chat.module.d.ts +8 -4
  21. package/chat/common/chat.service.d.ts +51 -0
  22. package/chat/{chat.directives.d.ts → common/models/default-model-fields.d.ts} +5 -4
  23. package/chat/common/models/message-box-options.d.ts +1 -1
  24. package/chat/common/models/model-fields.d.ts +111 -0
  25. package/chat/common/utils.d.ts +50 -0
  26. package/chat/l10n/messages.d.ts +40 -3
  27. package/chat/message-attachments.component.d.ts +1 -4
  28. package/chat/message-box.component.d.ts +54 -25
  29. package/chat/message-list.component.d.ts +18 -11
  30. package/chat/message-reference-content.component.d.ts +24 -0
  31. package/chat/message.component.d.ts +54 -6
  32. package/chat/suggested-actions.component.d.ts +17 -4
  33. package/chat/templates/header-template.directive.d.ts +24 -0
  34. package/chat/{message-box.directive.d.ts → templates/message-box.directive.d.ts} +1 -1
  35. package/chat/templates/status-template.directive.d.ts +24 -0
  36. package/chat/templates/suggestion-template.directive.d.ts +24 -0
  37. package/chat/templates/timestamp-template.directive.d.ts +28 -0
  38. package/codemods/template-transformer/index.js +94 -0
  39. package/codemods/utils.js +609 -0
  40. package/codemods/v20/chat-user.js +50 -0
  41. package/conversational-ui.module.d.ts +11 -7
  42. package/directives.d.ts +9 -5
  43. package/esm2022/chat/api/chat-file-interface.mjs +5 -0
  44. package/esm2022/chat/api/chat-suggestion.interface.mjs +5 -0
  45. package/esm2022/chat/api/file-action.mjs +5 -0
  46. package/esm2022/chat/api/file-download-event.interface.mjs +5 -0
  47. package/esm2022/chat/api/index.mjs +8 -0
  48. package/esm2022/chat/api/message-action.mjs +5 -0
  49. package/esm2022/chat/api/message-toolbar-visibility.mjs +5 -0
  50. package/esm2022/chat/api/message-width-mode.mjs +5 -0
  51. package/esm2022/chat/api/send-button-settings.mjs +5 -0
  52. package/esm2022/chat/attachment.component.mjs +1 -1
  53. package/esm2022/chat/builtin-actions.mjs +1 -1
  54. package/esm2022/chat/cards/hero-card.component.mjs +1 -1
  55. package/esm2022/chat/chat-file.component.mjs +141 -0
  56. package/esm2022/chat/chat-item.mjs +1 -0
  57. package/esm2022/chat/chat-view.mjs +2 -2
  58. package/esm2022/chat/chat.component.mjs +518 -57
  59. package/esm2022/chat/chat.module.mjs +8 -4
  60. package/esm2022/chat/common/chat.service.mjs +97 -0
  61. package/esm2022/chat/common/models/default-model-fields.mjs +26 -0
  62. package/esm2022/chat/common/models/model-fields.mjs +5 -0
  63. package/esm2022/chat/common/utils.mjs +127 -0
  64. package/esm2022/chat/l10n/messages.mjs +60 -5
  65. package/esm2022/chat/message-attachments.component.mjs +1 -4
  66. package/esm2022/chat/message-box.component.mjs +360 -111
  67. package/esm2022/chat/message-list.component.mjs +166 -96
  68. package/esm2022/chat/message-reference-content.component.mjs +75 -0
  69. package/esm2022/chat/message.component.mjs +448 -35
  70. package/esm2022/chat/suggested-actions.component.mjs +151 -41
  71. package/esm2022/chat/templates/header-template.directive.mjs +33 -0
  72. package/esm2022/chat/{message-box.directive.mjs → templates/message-box.directive.mjs} +1 -1
  73. package/esm2022/chat/templates/status-template.directive.mjs +33 -0
  74. package/esm2022/chat/templates/suggestion-template.directive.mjs +33 -0
  75. package/esm2022/chat/templates/timestamp-template.directive.mjs +39 -0
  76. package/esm2022/conversational-ui.module.mjs +12 -8
  77. package/esm2022/directives.mjs +12 -4
  78. package/esm2022/index.mjs +9 -3
  79. package/esm2022/package-metadata.mjs +2 -2
  80. package/fesm2022/progress-kendo-angular-conversational-ui.mjs +4986 -3125
  81. package/index.d.ts +10 -3
  82. package/package.json +29 -12
  83. /package/chat/{attachment-template.directive.d.ts → templates/attachment-template.directive.d.ts} +0 -0
  84. /package/chat/{message-template.directive.d.ts → templates/message-template.directive.d.ts} +0 -0
  85. /package/esm2022/chat/{attachment-template.directive.mjs → templates/attachment-template.directive.mjs} +0 -0
  86. /package/esm2022/chat/{message-template.directive.mjs → templates/message-template.directive.mjs} +0 -0
@@ -0,0 +1,609 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ "use strict";
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.tsComponentPropertyRemoval = exports.tsPropertyRemoval = exports.templateAttributeRemoval = exports.htmlAttributeRemoval = exports.htmlAttributeValueTransformer = exports.tsPropertyValueTransformer = exports.templateAttributeValueTransformer = exports.htmlAttributeTransformer = exports.htmlBoundAttributeTransformer = exports.htmlStaticAttributeTransformer = exports.tsPropertyTransformer = exports.templateAttributeTransformer = exports.templateBoundAttributeTransformer = exports.templateStaticAttributeTransformer = void 0;
11
+ const node_html_parser_1 = __importDefault(require("node-html-parser"));
12
+ const templateStaticAttributeTransformer = (root, tagName, attributeName, newAttributeName) => {
13
+ const elements = Array.from(root.getElementsByTagName(tagName)) || [];
14
+ for (const element of elements) {
15
+ // Handle static attributes like title="foo"
16
+ const staticAttr = element.getAttribute(attributeName);
17
+ if (staticAttr) {
18
+ element.setAttribute(newAttributeName, staticAttr);
19
+ element.removeAttribute(attributeName);
20
+ }
21
+ }
22
+ };
23
+ exports.templateStaticAttributeTransformer = templateStaticAttributeTransformer;
24
+ const templateBoundAttributeTransformer = (root, tagName, attributeName, newAttributeName, valueProperty) => {
25
+ const elements = Array.from(root.getElementsByTagName(tagName)) || [];
26
+ for (const element of elements) {
27
+ // Handle bound attributes like [title]="foo" or [title]="'foo'"
28
+ const boundAttr = element.getAttribute(`[${attributeName}]`);
29
+ if (boundAttr) {
30
+ const newValue = valueProperty ? `${boundAttr}.${valueProperty}` : boundAttr;
31
+ element.setAttribute(`[${newAttributeName}]`, newValue);
32
+ element.removeAttribute(`[${attributeName}]`);
33
+ }
34
+ }
35
+ };
36
+ exports.templateBoundAttributeTransformer = templateBoundAttributeTransformer;
37
+ const templateAttributeTransformer = (root, tagName, attributeName, newAttributeName) => {
38
+ (0, exports.templateBoundAttributeTransformer)(root, tagName, attributeName, newAttributeName);
39
+ (0, exports.templateStaticAttributeTransformer)(root, tagName, attributeName, newAttributeName);
40
+ };
41
+ exports.templateAttributeTransformer = templateAttributeTransformer;
42
+ const tsPropertyTransformer = (root, j, componentType, propertyName, newPropertyName, valueProperty) => {
43
+ // Find all class properties that are of type DropDownListComponent
44
+ const properties = new Set();
45
+ // Find properties with type annotations
46
+ root
47
+ .find(j.ClassProperty, {
48
+ typeAnnotation: {
49
+ typeAnnotation: {
50
+ typeName: {
51
+ name: componentType
52
+ }
53
+ }
54
+ }
55
+ })
56
+ .forEach(path => {
57
+ if (path.node.key.type === 'Identifier') {
58
+ properties.add(path.node.key.name);
59
+ }
60
+ });
61
+ // Find function parameters of type componentType
62
+ const parameters = new Set();
63
+ root
64
+ .find(j.FunctionDeclaration)
65
+ .forEach(path => {
66
+ if (path.node.params) {
67
+ path.node.params.forEach(param => {
68
+ if (param.type === 'Identifier' &&
69
+ param.typeAnnotation &&
70
+ param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
71
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
72
+ param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
73
+ parameters.add(param.name);
74
+ }
75
+ });
76
+ }
77
+ });
78
+ // Also check method declarations in classes
79
+ root
80
+ .find(j.ClassMethod)
81
+ .forEach(path => {
82
+ if (path.node.params) {
83
+ path.node.params.forEach(param => {
84
+ if (param.type === 'Identifier' &&
85
+ param.typeAnnotation &&
86
+ param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
87
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
88
+ param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
89
+ parameters.add(param.name);
90
+ }
91
+ });
92
+ }
93
+ });
94
+ // Also check arrow functions
95
+ root
96
+ .find(j.ArrowFunctionExpression)
97
+ .forEach(path => {
98
+ if (path.node.params) {
99
+ path.node.params.forEach(param => {
100
+ if (param.type === 'Identifier' &&
101
+ param.typeAnnotation &&
102
+ param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
103
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
104
+ param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
105
+ parameters.add(param.name);
106
+ }
107
+ });
108
+ }
109
+ });
110
+ // Find local variable declarations of type componentType
111
+ const localVariables = new Set();
112
+ root
113
+ .find(j.VariableDeclarator)
114
+ .forEach(path => {
115
+ if (path.node.id.type === 'Identifier' &&
116
+ path.node.id.typeAnnotation &&
117
+ path.node.id.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
118
+ path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
119
+ path.node.id.typeAnnotation.typeAnnotation.typeName.name === componentType) {
120
+ localVariables.add(path.node.id.name);
121
+ }
122
+ });
123
+ // Find all member expressions where title property is accessed on any componentType instance
124
+ root
125
+ .find(j.MemberExpression, {
126
+ property: {
127
+ type: 'Identifier',
128
+ name: propertyName
129
+ }
130
+ })
131
+ .filter(path => {
132
+ // Filter to only include accesses on properties that are componentType instances
133
+ if (path.node.object.type === 'MemberExpression' &&
134
+ path.node.object.property.type === 'Identifier') {
135
+ // handle properties of this
136
+ if (path.node.object.object.type === 'ThisExpression' &&
137
+ properties.has(path.node.object.property.name)) {
138
+ return true;
139
+ }
140
+ }
141
+ // Handle function parameters and local variables
142
+ if (path.node.object.type === 'Identifier') {
143
+ return parameters.has(path.node.object.name) || localVariables.has(path.node.object.name);
144
+ }
145
+ return false;
146
+ })
147
+ .forEach(path => {
148
+ // Replace old property name with new property name
149
+ if (path.node.property.type === 'Identifier') {
150
+ path.node.property.name = newPropertyName;
151
+ }
152
+ // If valueProperty is specified and this is part of an assignment,
153
+ // we need to also modify the right-hand side of the assignment
154
+ if (valueProperty) {
155
+ const assignmentExpression = path.parent;
156
+ if (assignmentExpression && assignmentExpression.value &&
157
+ assignmentExpression.value.type === 'AssignmentExpression' &&
158
+ assignmentExpression.value.left === path.node) {
159
+ const rightSide = assignmentExpression.value.right;
160
+ // Case 1: Right side is a member expression (e.g., this.user, obj.user) -> transform to this.user.id, obj.user.id
161
+ // Case 2: Right side is an identifier (e.g., user, foo) -> transform to user.id, foo.id
162
+ if (rightSide.type === 'MemberExpression' || rightSide.type === 'Identifier') {
163
+ const newRightSide = j.memberExpression(rightSide, j.identifier(valueProperty));
164
+ assignmentExpression.value.right = newRightSide;
165
+ }
166
+ // Case 3: Right side is object literal -> extract the valueProperty value
167
+ else if (rightSide.type === 'ObjectExpression') {
168
+ // Find the property that matches valueProperty
169
+ const targetProperty = rightSide.properties.find((prop) => prop.type === 'ObjectProperty' &&
170
+ prop.key &&
171
+ prop.key.type === 'Identifier' &&
172
+ prop.key.name === valueProperty);
173
+ if (targetProperty) {
174
+ // Replace the entire object literal with just the value of the target property
175
+ assignmentExpression.value.right = targetProperty.value;
176
+ }
177
+ }
178
+ }
179
+ }
180
+ });
181
+ };
182
+ exports.tsPropertyTransformer = tsPropertyTransformer;
183
+ const htmlStaticAttributeTransformer = (fileInfo, tagName, oldName, newName) => {
184
+ const fileContent = fileInfo.source;
185
+ const root = (0, node_html_parser_1.default)(fileContent);
186
+ let modified = false;
187
+ const elements = Array.from(root.querySelectorAll(tagName));
188
+ for (const element of elements) {
189
+ const staticAttr = element.getAttribute(oldName);
190
+ if (staticAttr) {
191
+ element.removeAttribute(oldName);
192
+ element.setAttribute(newName, staticAttr);
193
+ modified = true;
194
+ }
195
+ }
196
+ if (modified) {
197
+ return root.toString();
198
+ }
199
+ return fileContent;
200
+ };
201
+ exports.htmlStaticAttributeTransformer = htmlStaticAttributeTransformer;
202
+ const htmlBoundAttributeTransformer = (fileInfo, tagName, oldName, newName, valueProperty) => {
203
+ const fileContent = fileInfo.source;
204
+ const root = (0, node_html_parser_1.default)(fileContent);
205
+ let modified = false;
206
+ const elements = Array.from(root.querySelectorAll(tagName));
207
+ for (const element of elements) {
208
+ const boundAttr = element.getAttribute(`[${oldName}]`);
209
+ if (boundAttr) {
210
+ element.removeAttribute(`[${oldName}]`);
211
+ // If valueProperty is provided, append it to the bound value
212
+ const newValue = valueProperty ? `${boundAttr}.${valueProperty}` : boundAttr;
213
+ element.setAttribute(`[${newName}]`, newValue);
214
+ modified = true;
215
+ }
216
+ }
217
+ if (modified) {
218
+ return root.toString();
219
+ }
220
+ return fileContent;
221
+ };
222
+ exports.htmlBoundAttributeTransformer = htmlBoundAttributeTransformer;
223
+ const htmlAttributeTransformer = (fileInfo, tagName, oldName, newName) => {
224
+ let content = (0, exports.htmlBoundAttributeTransformer)(fileInfo, tagName, oldName, newName);
225
+ content = (0, exports.htmlStaticAttributeTransformer)({ path: fileInfo.path, source: content }, tagName, oldName, newName);
226
+ return content;
227
+ };
228
+ exports.htmlAttributeTransformer = htmlAttributeTransformer;
229
+ const templateAttributeValueTransformer = (root, tagName, attributeName, oldAttributeValue, newAttributeValue) => {
230
+ const elements = Array.from(root.getElementsByTagName(tagName)) || [];
231
+ for (const element of elements) {
232
+ // Handle bound attributes (e.g., [showText]="'overflow'")
233
+ const boundAttr = element.getAttribute(`[${attributeName}]`);
234
+ if (boundAttr === `'${oldAttributeValue}'`) {
235
+ // For bound literals like [showText]="'overflow'" or [showText]="\"overflow\""
236
+ element.setAttribute(`[${attributeName}]`, boundAttr.replace(oldAttributeValue, newAttributeValue));
237
+ }
238
+ // Handle static attributes like title="foo"
239
+ const staticAttrValue = element.getAttribute(attributeName);
240
+ if (staticAttrValue === oldAttributeValue) {
241
+ element.setAttribute(attributeName, newAttributeValue);
242
+ }
243
+ }
244
+ };
245
+ exports.templateAttributeValueTransformer = templateAttributeValueTransformer;
246
+ const tsPropertyValueTransformer = (root, j, typeName, oldValue, newValue) => {
247
+ // 1. Find all class properties with the specified type
248
+ root
249
+ .find(j.ClassProperty)
250
+ .filter(path => {
251
+ // Check if the property has a type annotation matching the specified type
252
+ if (path.node.typeAnnotation?.typeAnnotation &&
253
+ path.node.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
254
+ path.node.typeAnnotation.typeAnnotation.typeName &&
255
+ path.node.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
256
+ path.node.typeAnnotation.typeAnnotation.typeName.name === typeName) {
257
+ return true;
258
+ }
259
+ return false;
260
+ })
261
+ .forEach(path => {
262
+ // Update the value if it matches the old value
263
+ if (path.node.value &&
264
+ path.node.value.type === 'StringLiteral' &&
265
+ path.node.value.value === oldValue) {
266
+ path.node.value.value = newValue;
267
+ }
268
+ });
269
+ // First, collect all variables with the specified type
270
+ root
271
+ .find(j.VariableDeclarator)
272
+ .filter(path => {
273
+ if (path.node.id.type === 'Identifier' &&
274
+ path.node.id.typeAnnotation?.typeAnnotation &&
275
+ path.node.id.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
276
+ path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
277
+ path.node.id.typeAnnotation.typeAnnotation.typeName.name === typeName) {
278
+ return true;
279
+ }
280
+ return false;
281
+ })
282
+ .forEach(path => {
283
+ if (path.node.id.type === 'Identifier') {
284
+ // Also update the initial value if it matches
285
+ if (path.node.init &&
286
+ path.node.init.type === 'StringLiteral' &&
287
+ path.node.init.value === oldValue) {
288
+ path.node.init.value = newValue;
289
+ }
290
+ }
291
+ });
292
+ // 3. Update literals in assignment expressions
293
+ root
294
+ .find(j.AssignmentExpression)
295
+ .filter(path => {
296
+ // Only process string literals with the old value
297
+ return path.node.right.type === 'StringLiteral' &&
298
+ path.node.right.value === oldValue;
299
+ })
300
+ .forEach(path => {
301
+ // Update the value
302
+ path.node.right.value = newValue;
303
+ });
304
+ // 4. Also look for string literals in attributes within JSX elements
305
+ root
306
+ .find(j.JSXAttribute, {
307
+ value: {
308
+ type: 'StringLiteral',
309
+ value: oldValue
310
+ }
311
+ })
312
+ .forEach(path => {
313
+ if (path.node.value?.type === 'StringLiteral') {
314
+ path.node.value.value = newValue;
315
+ }
316
+ });
317
+ };
318
+ exports.tsPropertyValueTransformer = tsPropertyValueTransformer;
319
+ const htmlAttributeValueTransformer = (fileInfo, tagName, attributeName, oldValue, newValue) => {
320
+ // Read file content from fileInfo
321
+ const fileContent = fileInfo.source;
322
+ // Parse the HTML content
323
+ const root = (0, node_html_parser_1.default)(fileContent);
324
+ // Find all elements matching the tagName
325
+ const elements = root.querySelectorAll(tagName);
326
+ let modified = false;
327
+ // Process each element
328
+ for (const element of elements) {
329
+ // Handle static attributes (e.g., showText="overflow")
330
+ const staticAttr = element.getAttribute(attributeName);
331
+ if (staticAttr === oldValue) {
332
+ element.setAttribute(attributeName, newValue);
333
+ modified = true;
334
+ console.log(`Modified static attribute ${attributeName} from "${oldValue}" to "${newValue}" in element:`, element.toString().substring(0, 100));
335
+ }
336
+ // Handle bound attributes (e.g., [showText]="overflow")
337
+ const boundAttr = element.getAttribute(`[${attributeName}]`);
338
+ if (boundAttr) {
339
+ // For bound literals like [showText]="'overflow'" or [showText]="\"overflow\""
340
+ if (boundAttr === `'${oldValue}'` || boundAttr === `"${oldValue}"`) {
341
+ const updatedValue = boundAttr.replace(oldValue, newValue);
342
+ element.setAttribute(`[${attributeName}]`, updatedValue);
343
+ modified = true;
344
+ console.log(`Modified bound attribute [${attributeName}] from "${boundAttr}" to "${updatedValue}" in element:`, element.toString().substring(0, 100));
345
+ }
346
+ }
347
+ }
348
+ // Return modified content if changes were made
349
+ if (modified) {
350
+ const updatedContent = root.toString();
351
+ return updatedContent;
352
+ }
353
+ // Return original content if no changes were made or if there was an error
354
+ return fileContent;
355
+ };
356
+ exports.htmlAttributeValueTransformer = htmlAttributeValueTransformer;
357
+ const htmlAttributeRemoval = (fileInfo, tagName, attributeName, propertyToRemove) => {
358
+ const filePath = fileInfo.path;
359
+ const fileContent = fileInfo.source;
360
+ const root = (0, node_html_parser_1.default)(fileContent);
361
+ // Use the same logic as templateAttributeRemoval
362
+ const elements = root.querySelectorAll(tagName);
363
+ for (const element of elements) {
364
+ // Look for bound attribute (e.g., [scrollable]="...")
365
+ const boundAttr = element.getAttribute(`[${attributeName}]`);
366
+ if (boundAttr) {
367
+ // Check if it's an object literal
368
+ if (boundAttr.trim().startsWith('{') && boundAttr.trim().endsWith('}')) {
369
+ // Process object literal like {mouseScrollSpeed: 10000}
370
+ const objectLiteral = boundAttr.trim();
371
+ // Build a regex that matches the property and its value
372
+ // This handles various formats like {prop: value}, { prop: value }, etc.
373
+ const propRegex = new RegExp(`\\s*${propertyToRemove}\\s*:\\s*[^,}]+\\s*(,\\s*)?`, 'g');
374
+ // Remove the property and any trailing comma
375
+ let newObjectLiteral = objectLiteral.replace(propRegex, '');
376
+ // Fix syntax if we removed the last property with trailing comma
377
+ newObjectLiteral = newObjectLiteral.replace(/,\s*}$/, '}');
378
+ // If the object is now empty, remove the attribute completely
379
+ if (newObjectLiteral === '{}') {
380
+ element.removeAttribute(`[${attributeName}]`);
381
+ }
382
+ else {
383
+ element.setAttribute(`[${attributeName}]`, newObjectLiteral);
384
+ }
385
+ }
386
+ // Check if it's a variable reference to an object
387
+ else {
388
+ // For variable references, we can't modify them in the template
389
+ // We should warn the user or handle this case specially
390
+ console.warn(`Cannot remove property from variable reference: ${boundAttr} in file ${filePath}`);
391
+ }
392
+ }
393
+ }
394
+ // Return the modified HTML content
395
+ return root.toString();
396
+ };
397
+ exports.htmlAttributeRemoval = htmlAttributeRemoval;
398
+ /**
399
+ * Removes a specified property from an object binding in HTML templates
400
+ *
401
+ * @param root - The HTML root element
402
+ * @param tagName - The tag to search for (e.g., 'kendo-tabstrip')
403
+ * @param attributeName - The attribute containing the object binding (e.g., 'scrollable')
404
+ * @param propertyToRemove - The property to remove from the object (e.g., 'mouseScrollSpeed')
405
+ */
406
+ const templateAttributeRemoval = (root, tagName, attributeName, propertyToRemove) => {
407
+ const elements = root.querySelectorAll(tagName);
408
+ for (const element of elements) {
409
+ // Look for bound attribute (e.g., [scrollable]="...")
410
+ const boundAttr = element.getAttribute(`[${attributeName}]`);
411
+ if (boundAttr) {
412
+ // Check if it's an object literal
413
+ if (boundAttr.trim().startsWith('{') && boundAttr.trim().endsWith('}')) {
414
+ // Process object literal like {mouseScrollSpeed: 10000}
415
+ const objectLiteral = boundAttr.trim();
416
+ // Build a regex that matches the property and its value
417
+ // This handles various formats like {prop: value}, { prop: value }, etc.
418
+ const propRegex = new RegExp(`\\s*${propertyToRemove}\\s*:\\s*[^,}]+\\s*(,\\s*)?`, 'g');
419
+ // Remove the property and any trailing comma
420
+ let newObjectLiteral = objectLiteral.replace(propRegex, '');
421
+ // Fix syntax if we removed the last property with trailing comma
422
+ newObjectLiteral = newObjectLiteral.replace(/,\s*}$/, '}');
423
+ // If the object is now empty, remove the attribute completely
424
+ if (newObjectLiteral === '{}') {
425
+ element.removeAttribute(`[${attributeName}]`);
426
+ }
427
+ else {
428
+ element.setAttribute(`[${attributeName}]`, newObjectLiteral);
429
+ }
430
+ }
431
+ // Check if it's a variable reference to an object
432
+ else {
433
+ // For variable references, we can't modify them in the template
434
+ // We should warn the user or handle this case specially
435
+ console.warn(`Cannot remove property from variable reference: ${boundAttr}`);
436
+ }
437
+ }
438
+ }
439
+ };
440
+ exports.templateAttributeRemoval = templateAttributeRemoval;
441
+ /**
442
+ * Removes a property from object literals of a specified type
443
+ *
444
+ * @param root - The AST root
445
+ * @param j - The JSCodeshift instance
446
+ * @param typeName - The type to target (e.g., 'TabStripScrollableSettings')
447
+ * @param propertyToRemove - The property to remove (e.g., 'mouseScrollSpeed')
448
+ */
449
+ function tsPropertyRemoval(rootSource, j, typeName, propertyName) {
450
+ // Find class properties that have the specified type
451
+ rootSource
452
+ .find(j.ClassProperty, {
453
+ typeAnnotation: {
454
+ typeAnnotation: {
455
+ typeName: {
456
+ name: typeName
457
+ }
458
+ }
459
+ }
460
+ })
461
+ .forEach(path => {
462
+ // Check if there's an object literal initializer
463
+ if (path.node.value && path.node.value.type === 'ObjectExpression') {
464
+ const properties = path.node.value.properties;
465
+ // Find the property we want to remove - safely handle different property types
466
+ const propIndex = properties.findIndex((p) => p.type === 'ObjectProperty' &&
467
+ p.key &&
468
+ p.key.type === 'Identifier' &&
469
+ p.key.name === propertyName);
470
+ if (propIndex !== -1) {
471
+ // If property exists, remove it
472
+ // Case 1: If it's the only property, remove the entire class property
473
+ if (properties.length === 1) {
474
+ j(path).remove();
475
+ }
476
+ // Case 2: If there are other properties, just remove this one property
477
+ else {
478
+ properties.splice(propIndex, 1);
479
+ }
480
+ }
481
+ }
482
+ });
483
+ // Also handle property assignments (e.g., in methods like ngOnInit)
484
+ rootSource
485
+ .find(j.AssignmentExpression, {
486
+ left: {
487
+ type: 'MemberExpression',
488
+ object: {
489
+ type: 'MemberExpression'
490
+ },
491
+ property: {
492
+ name: propertyName
493
+ }
494
+ }
495
+ })
496
+ .forEach(path => {
497
+ j(path).remove();
498
+ });
499
+ return rootSource;
500
+ }
501
+ exports.tsPropertyRemoval = tsPropertyRemoval;
502
+ /**
503
+ * Removes assignments to a specific nested property of a component
504
+ *
505
+ * @param root - The AST root
506
+ * @param j - The JSCodeshift instance
507
+ * @param componentType - The component type to target (e.g., 'TabStripComponent')
508
+ * @param componentProperty - The component property (e.g., 'scrollable')
509
+ * @param propertyToRemove - The nested property to remove assignments to (e.g., 'mouseScrollSpeed')
510
+ */
511
+ const tsComponentPropertyRemoval = (root, j, componentType, componentProperty, propertyToRemove) => {
512
+ // CASE 1: Handle direct property assignments like: foo.scrollable.mouseScrollSpeed = 3000;
513
+ root
514
+ .find(j.AssignmentExpression)
515
+ .filter((path) => {
516
+ const { left } = path.value;
517
+ // Check if this is a member expression assignment
518
+ if (left && left.type === 'MemberExpression') {
519
+ // Check if we're accessing the property to remove
520
+ if (left.property && left.property.name === propertyToRemove) {
521
+ // Check if we're accessing it from component.componentProperty
522
+ const obj = left.object;
523
+ if (obj && obj.type === 'MemberExpression' &&
524
+ obj.property && obj.property.name === componentProperty) {
525
+ // Now check if the base object is our component type
526
+ return isComponentTypeMatch(root, j, obj.object, componentType);
527
+ }
528
+ }
529
+ }
530
+ return false;
531
+ })
532
+ .forEach((path) => {
533
+ // Remove the entire statement
534
+ j(path).closest(j.ExpressionStatement).remove();
535
+ });
536
+ // CASE 2 & 3: Handle object assignments like: foo.scrollable = { mouseScrollSpeed: 3000, ... };
537
+ root
538
+ .find(j.AssignmentExpression)
539
+ .filter((path) => {
540
+ const { left, right } = path.value;
541
+ // Check if this assigns to component.componentProperty
542
+ if (left && left.type === 'MemberExpression' &&
543
+ left.property && left.property.name === componentProperty &&
544
+ right && right.type === 'ObjectExpression') {
545
+ // Check if the base object is our component type
546
+ return isComponentTypeMatch(root, j, left.object, componentType);
547
+ }
548
+ return false;
549
+ })
550
+ .forEach((path) => {
551
+ const properties = path.value.right.properties;
552
+ // Find the property we want to remove
553
+ const propIndex = properties.findIndex((p) => p && p.type === 'ObjectProperty' &&
554
+ p.key && p.key.type === 'Identifier' &&
555
+ p.key.name === propertyToRemove);
556
+ if (propIndex !== -1) {
557
+ // Case 2: If it's the only property, remove the entire statement
558
+ if (properties.length === 1) {
559
+ j(path).closest(j.ExpressionStatement).remove();
560
+ }
561
+ // Case 3: If there are other properties, just remove this one property
562
+ else {
563
+ properties.splice(propIndex, 1);
564
+ }
565
+ }
566
+ });
567
+ return root;
568
+ };
569
+ exports.tsComponentPropertyRemoval = tsComponentPropertyRemoval;
570
+ // Helper function to check if a node is a component of the specified type
571
+ function isComponentTypeMatch(root, j, node, componentType) {
572
+ if (!node)
573
+ return false;
574
+ // Case 1: Direct match for 'this.propertyName'
575
+ if (node.type === 'ThisExpression') {
576
+ return true; // Assuming 'this' refers to the component class
577
+ }
578
+ // Case 2: Function parameter
579
+ if (node.type === 'Identifier') {
580
+ const paramName = node.name;
581
+ // Check function parameters
582
+ return root
583
+ .find(j.Function)
584
+ .some(path => {
585
+ return path.node.params && path.node.params.some((param) => param.type === 'Identifier' &&
586
+ param.name === paramName &&
587
+ param.typeAnnotation?.typeAnnotation?.typeName?.name === componentType);
588
+ });
589
+ }
590
+ // Case 3: Member expression (obj.prop)
591
+ if (node.type === 'MemberExpression') {
592
+ // This would need more complex logic to determine if the object is of the right type
593
+ // For now, we can check if it's a property that has been declared with the right type
594
+ if (node.object.type === 'ThisExpression' && node.property.type === 'Identifier') {
595
+ const propName = node.property.name;
596
+ return root
597
+ .find(j.ClassProperty, {
598
+ key: { name: propName },
599
+ typeAnnotation: {
600
+ typeAnnotation: {
601
+ typeName: { name: componentType }
602
+ }
603
+ }
604
+ })
605
+ .size() > 0;
606
+ }
607
+ }
608
+ return false;
609
+ }
@@ -0,0 +1,50 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ "use strict";
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || function (mod) {
23
+ if (mod && mod.__esModule) return mod;
24
+ var result = {};
25
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
26
+ __setModuleDefault(result, mod);
27
+ return result;
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ const fs = __importStar(require("fs"));
31
+ const index_1 = require("../template-transformer/index");
32
+ const utils_1 = require("../utils");
33
+ function default_1(fileInfo, api) {
34
+ const filePath = fileInfo.path;
35
+ if (filePath.endsWith('.html')) {
36
+ let updatedContent = fileInfo.source;
37
+ updatedContent = (0, utils_1.htmlBoundAttributeTransformer)({ ...fileInfo, source: updatedContent }, 'kendo-chat', 'user', 'authorId', 'id');
38
+ // Only write to file once after all transformations
39
+ fs.writeFileSync(filePath, updatedContent, 'utf-8');
40
+ return;
41
+ }
42
+ const j = api.jscodeshift;
43
+ const rootSource = j(fileInfo.source);
44
+ (0, index_1.templateTransformer)(rootSource, j, (root) => {
45
+ (0, utils_1.templateBoundAttributeTransformer)(root, 'kendo-chat', 'user', 'authorId', 'id');
46
+ });
47
+ (0, utils_1.tsPropertyTransformer)(rootSource, j, 'ChatComponent', 'user', 'authorId', 'id');
48
+ return rootSource.toSource();
49
+ }
50
+ exports.default = default_1;