@progress/kendo-angular-grid 21.0.0-develop.9 → 21.0.1-develop.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.
Files changed (36) hide show
  1. package/codemods/utils.js +485 -327
  2. package/codemods/v20/grid-kendogridgroupbinding.js +6 -6
  3. package/codemods/v21/grid-gridtoolbaraiopenevent.js +14 -0
  4. package/codemods/v21/grid-gridtoolbaraipromptrequestevent.js +14 -0
  5. package/codemods/v21/grid-gridtoolbaraipromptsettings.js +14 -0
  6. package/codemods/v21/grid-gridtoolbarairequestoptions.js +14 -0
  7. package/codemods/v21/grid-gridtoolbarairesponseerrorevent.js +14 -0
  8. package/codemods/v21/grid-gridtoolbaraiwindowsettings.js +14 -0
  9. package/column-menu/column-chooser.component.d.ts +0 -1
  10. package/common/id.service.d.ts +1 -0
  11. package/common/provider.service.d.ts +4 -0
  12. package/esm2022/column-menu/column-chooser.component.mjs +2 -7
  13. package/esm2022/columns/column-base.mjs +1 -1
  14. package/esm2022/common/id.service.mjs +3 -0
  15. package/esm2022/common/provider.service.mjs +2 -0
  16. package/esm2022/dragdrop/drag-hint.service.mjs +6 -2
  17. package/esm2022/excel/excel.component.mjs +13 -2
  18. package/esm2022/grid.component.mjs +18 -0
  19. package/esm2022/localization/messages.mjs +19 -1
  20. package/esm2022/navigation/navigation.service.mjs +47 -1
  21. package/esm2022/package-metadata.mjs +2 -2
  22. package/esm2022/pdf/pdf.component.mjs +6 -0
  23. package/esm2022/rendering/list.component.mjs +16 -5
  24. package/esm2022/rendering/toolbar/tools/ai-assistant/ai-assistant.component.mjs +557 -29
  25. package/esm2022/rendering/toolbar/tools/ai-assistant/models.mjs +2 -2
  26. package/esm2022/row-reordering/row-reorder.service.mjs +28 -0
  27. package/excel/excel.component.d.ts +6 -2
  28. package/fesm2022/progress-kendo-angular-grid.mjs +717 -49
  29. package/localization/messages.d.ts +13 -1
  30. package/navigation/navigation.service.d.ts +1 -0
  31. package/package.json +58 -25
  32. package/rendering/toolbar/tools/ai-assistant/ai-assistant.component.d.ts +26 -5
  33. package/rendering/toolbar/tools/ai-assistant/ai-tool.directive.d.ts +8 -8
  34. package/rendering/toolbar/tools/ai-assistant/models.d.ts +65 -33
  35. package/row-reordering/row-reorder.service.d.ts +10 -1
  36. package/schematics/ngAdd/index.js +7 -7
package/codemods/utils.js CHANGED
@@ -7,9 +7,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  return (mod && mod.__esModule) ? mod : { "default": mod };
8
8
  };
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.tsComponentPropertyRemoval = 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;
10
+ exports.tsInterfaceTransformer = exports.tsComponentPropertyRemoval = exports.templateAttributeRemoval = exports.htmlAttributeRemoval = exports.htmlAttributeValueTransformer = exports.tsPropertyValueTransformer = exports.templateAttributeValueTransformer = exports.htmlEventTransformer = exports.htmlAttributeTransformer = exports.htmlBoundAttributeTransformer = exports.htmlStaticAttributeTransformer = exports.tsPropertyTransformer = exports.templateAttributeTransformer = exports.templateBoundAttributeTransformer = exports.templateStaticAttributeTransformer = exports.templateEventTransformer = exports.blockTextElements = void 0;
11
+ exports.hasKendoInTemplate = hasKendoInTemplate;
11
12
  exports.tsPropertyRemoval = tsPropertyRemoval;
12
13
  const node_html_parser_1 = __importDefault(require("node-html-parser"));
14
+ exports.blockTextElements = {
15
+ script: true,
16
+ noscript: true,
17
+ style: true,
18
+ pre: true,
19
+ };
20
+ function hasKendoInTemplate(source) {
21
+ const kendoPattern = /(<kendo-[^>\s]+|<[^>]*\s+kendo[A-Z][^>\s]*)/g;
22
+ return kendoPattern.test(source);
23
+ }
24
+ const templateEventTransformer = (root, tagName, eventName, newEventName) => {
25
+ const elements = Array.from(root.getElementsByTagName(tagName)) || [];
26
+ for (const element of elements) {
27
+ // Handle event bindings like (actionClick)="handler($event)"
28
+ const eventAttr = element.getAttribute(`(${eventName})`);
29
+ if (eventAttr) {
30
+ element.setAttribute(`(${newEventName})`, eventAttr);
31
+ element.removeAttribute(`(${eventName})`);
32
+ }
33
+ }
34
+ };
35
+ exports.templateEventTransformer = templateEventTransformer;
13
36
  const templateStaticAttributeTransformer = (root, tagName, attributeName, newAttributeName) => {
14
37
  const elements = Array.from(root.getElementsByTagName(tagName)) || [];
15
38
  for (const element of elements) {
@@ -22,13 +45,14 @@ const templateStaticAttributeTransformer = (root, tagName, attributeName, newAtt
22
45
  }
23
46
  };
24
47
  exports.templateStaticAttributeTransformer = templateStaticAttributeTransformer;
25
- const templateBoundAttributeTransformer = (root, tagName, attributeName, newAttributeName) => {
48
+ const templateBoundAttributeTransformer = (root, tagName, attributeName, newAttributeName, valueProperty) => {
26
49
  const elements = Array.from(root.getElementsByTagName(tagName)) || [];
27
50
  for (const element of elements) {
28
51
  // Handle bound attributes like [title]="foo" or [title]="'foo'"
29
52
  const boundAttr = element.getAttribute(`[${attributeName}]`);
30
53
  if (boundAttr) {
31
- element.setAttribute(`[${newAttributeName}]`, boundAttr);
54
+ const newValue = valueProperty ? `${boundAttr}.${valueProperty}` : boundAttr;
55
+ element.setAttribute(`[${newAttributeName}]`, newValue);
32
56
  element.removeAttribute(`[${attributeName}]`);
33
57
  }
34
58
  }
@@ -39,94 +63,141 @@ const templateAttributeTransformer = (root, tagName, attributeName, newAttribute
39
63
  (0, exports.templateStaticAttributeTransformer)(root, tagName, attributeName, newAttributeName);
40
64
  };
41
65
  exports.templateAttributeTransformer = templateAttributeTransformer;
42
- const tsPropertyTransformer = (root, j, componentType, propertyName, newPropertyName) => {
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: {
66
+ const tsPropertyTransformer = (source, root, j, componentType, propertyName, newPropertyName, valueProperty) => {
67
+ if (source.includes(componentType)) {
68
+ // Find all class properties that are of type DropDownListComponent
69
+ const properties = new Set();
70
+ // Find properties with type annotations
71
+ root.find(j.ClassProperty, {
49
72
  typeAnnotation: {
50
- typeName: {
51
- name: componentType
52
- }
73
+ typeAnnotation: {
74
+ typeName: {
75
+ name: componentType,
76
+ },
77
+ },
78
+ },
79
+ }).forEach((path) => {
80
+ if (path.node.key.type === 'Identifier') {
81
+ properties.add(path.node.key.name);
53
82
  }
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);
83
+ });
84
+ // Find function parameters of type componentType
85
+ const parameters = new Set();
86
+ root.find(j.FunctionDeclaration).forEach((path) => {
87
+ if (path.node.params) {
88
+ path.node.params.forEach((param) => {
89
+ if (param.type === 'Identifier' &&
90
+ param.typeAnnotation &&
91
+ param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
92
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
93
+ param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
94
+ parameters.add(param.name);
95
+ }
96
+ });
97
+ }
98
+ });
99
+ // Also check method declarations in classes
100
+ root.find(j.ClassMethod).forEach((path) => {
101
+ if (path.node.params) {
102
+ path.node.params.forEach((param) => {
103
+ if (param.type === 'Identifier' &&
104
+ param.typeAnnotation &&
105
+ param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
106
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
107
+ param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
108
+ parameters.add(param.name);
109
+ }
110
+ });
111
+ }
112
+ });
113
+ // Also check arrow functions
114
+ root.find(j.ArrowFunctionExpression).forEach((path) => {
115
+ if (path.node.params) {
116
+ path.node.params.forEach((param) => {
117
+ if (param.type === 'Identifier' &&
118
+ param.typeAnnotation &&
119
+ param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
120
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
121
+ param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
122
+ parameters.add(param.name);
123
+ }
124
+ });
125
+ }
126
+ });
127
+ // Find local variable declarations of type componentType
128
+ const localVariables = new Set();
129
+ root.find(j.VariableDeclarator).forEach((path) => {
130
+ if (path.node.id.type === 'Identifier' &&
131
+ path.node.id.typeAnnotation &&
132
+ path.node.id.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
133
+ path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
134
+ path.node.id.typeAnnotation.typeAnnotation.typeName.name === componentType) {
135
+ localVariables.add(path.node.id.name);
136
+ }
137
+ });
138
+ // Find all member expressions where title property is accessed on any componentType instance
139
+ root.find(j.MemberExpression, {
140
+ property: {
141
+ type: 'Identifier',
142
+ name: propertyName,
143
+ },
144
+ })
145
+ .filter((path) => {
146
+ // Filter to only include accesses on properties that are componentType instances
147
+ if (path.node.object.type === 'MemberExpression' && path.node.object.property.type === 'Identifier') {
148
+ // handle properties of this
149
+ if (path.node.object.object.type === 'ThisExpression' &&
150
+ properties.has(path.node.object.property.name)) {
151
+ return true;
74
152
  }
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);
153
+ }
154
+ // Handle function parameters and local variables
155
+ if (path.node.object.type === 'Identifier') {
156
+ return parameters.has(path.node.object.name) || localVariables.has(path.node.object.name);
157
+ }
158
+ return false;
159
+ })
160
+ .forEach((path) => {
161
+ // Replace old property name with new property name
162
+ if (path.node.property.type === 'Identifier') {
163
+ path.node.property.name = newPropertyName;
164
+ }
165
+ // If valueProperty is specified and this is part of an assignment,
166
+ // we need to also modify the right-hand side of the assignment
167
+ if (valueProperty) {
168
+ const assignmentExpression = path.parent;
169
+ if (assignmentExpression &&
170
+ assignmentExpression.value &&
171
+ assignmentExpression.value.type === 'AssignmentExpression' &&
172
+ assignmentExpression.value.left === path.node) {
173
+ const rightSide = assignmentExpression.value.right;
174
+ // Case 1: Right side is a member expression (e.g., this.user, obj.user) -> transform to this.user.id, obj.user.id
175
+ // Case 2: Right side is an identifier (e.g., user, foo) -> transform to user.id, foo.id
176
+ if (rightSide.type === 'MemberExpression' || rightSide.type === 'Identifier') {
177
+ const newRightSide = j.memberExpression(rightSide, j.identifier(valueProperty));
178
+ assignmentExpression.value.right = newRightSide;
179
+ }
180
+ // Case 3: Right side is object literal -> extract the valueProperty value
181
+ else if (rightSide.type === 'ObjectExpression') {
182
+ // Find the property that matches valueProperty
183
+ const targetProperty = rightSide.properties.find((prop) => prop.type === 'ObjectProperty' &&
184
+ prop.key &&
185
+ prop.key.type === 'Identifier' &&
186
+ prop.key.name === valueProperty);
187
+ if (targetProperty) {
188
+ // Replace the entire object literal with just the value of the target property
189
+ assignmentExpression.value.right = targetProperty.value;
190
+ }
191
+ }
90
192
  }
91
- });
92
- }
93
- });
94
- // Find all member expressions where title property is accessed on any componentType instance
95
- root
96
- .find(j.MemberExpression, {
97
- property: {
98
- type: 'Identifier',
99
- name: propertyName
100
- }
101
- })
102
- .filter(path => {
103
- // Filter to only include accesses on properties that are componentType instances
104
- if (path.node.object.type === 'MemberExpression' &&
105
- path.node.object.property.type === 'Identifier') {
106
- // handle properties of this
107
- if (path.node.object.object.type === 'ThisExpression' &&
108
- properties.has(path.node.object.property.name)) {
109
- return true;
110
193
  }
111
- }
112
- // Handle function parameters
113
- if (path.node.object.type === 'Identifier' &&
114
- parameters.has(path.node.object.name)) {
115
- return true;
116
- }
117
- return false;
118
- })
119
- .forEach(path => {
120
- // Replace old property name with new property name
121
- if (path.node.property.type === 'Identifier') {
122
- path.node.property.name = newPropertyName;
123
- }
124
- });
194
+ });
195
+ }
125
196
  };
126
197
  exports.tsPropertyTransformer = tsPropertyTransformer;
127
198
  const htmlStaticAttributeTransformer = (fileInfo, tagName, oldName, newName) => {
128
199
  const fileContent = fileInfo.source;
129
- const root = (0, node_html_parser_1.default)(fileContent);
200
+ const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
130
201
  let modified = false;
131
202
  const elements = Array.from(root.querySelectorAll(tagName));
132
203
  for (const element of elements) {
@@ -143,16 +214,18 @@ const htmlStaticAttributeTransformer = (fileInfo, tagName, oldName, newName) =>
143
214
  return fileContent;
144
215
  };
145
216
  exports.htmlStaticAttributeTransformer = htmlStaticAttributeTransformer;
146
- const htmlBoundAttributeTransformer = (fileInfo, tagName, oldName, newName) => {
217
+ const htmlBoundAttributeTransformer = (fileInfo, tagName, oldName, newName, valueProperty) => {
147
218
  const fileContent = fileInfo.source;
148
- const root = (0, node_html_parser_1.default)(fileContent);
219
+ const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
149
220
  let modified = false;
150
221
  const elements = Array.from(root.querySelectorAll(tagName));
151
222
  for (const element of elements) {
152
223
  const boundAttr = element.getAttribute(`[${oldName}]`);
153
224
  if (boundAttr) {
154
225
  element.removeAttribute(`[${oldName}]`);
155
- element.setAttribute(`[${newName}]`, boundAttr);
226
+ // If valueProperty is provided, append it to the bound value
227
+ const newValue = valueProperty ? `${boundAttr}.${valueProperty}` : boundAttr;
228
+ element.setAttribute(`[${newName}]`, newValue);
156
229
  modified = true;
157
230
  }
158
231
  }
@@ -168,6 +241,26 @@ const htmlAttributeTransformer = (fileInfo, tagName, oldName, newName) => {
168
241
  return content;
169
242
  };
170
243
  exports.htmlAttributeTransformer = htmlAttributeTransformer;
244
+ const htmlEventTransformer = (fileInfo, tagName, oldEventName, newEventName) => {
245
+ const fileContent = fileInfo.source;
246
+ const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
247
+ let modified = false;
248
+ const elements = Array.from(root.querySelectorAll(tagName));
249
+ for (const element of elements) {
250
+ // Handle event bindings like (actionClick)="handler($event)"
251
+ const eventAttr = element.getAttribute(`(${oldEventName})`);
252
+ if (eventAttr) {
253
+ element.removeAttribute(`(${oldEventName})`);
254
+ element.setAttribute(`(${newEventName})`, eventAttr);
255
+ modified = true;
256
+ }
257
+ }
258
+ if (modified) {
259
+ return root.toString();
260
+ }
261
+ return fileContent;
262
+ };
263
+ exports.htmlEventTransformer = htmlEventTransformer;
171
264
  const templateAttributeValueTransformer = (root, tagName, attributeName, oldAttributeValue, newAttributeValue) => {
172
265
  const elements = Array.from(root.getElementsByTagName(tagName)) || [];
173
266
  for (const element of elements) {
@@ -185,91 +278,67 @@ const templateAttributeValueTransformer = (root, tagName, attributeName, oldAttr
185
278
  }
186
279
  };
187
280
  exports.templateAttributeValueTransformer = templateAttributeValueTransformer;
188
- const tsPropertyValueTransformer = (root, j, typeName, oldValue, newValue) => {
189
- // 1. Find all class properties with the specified type
190
- root
191
- .find(j.ClassProperty)
192
- .filter(path => {
193
- // Check if the property has a type annotation matching the specified type
194
- if (path.node.typeAnnotation?.typeAnnotation &&
195
- path.node.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
196
- path.node.typeAnnotation.typeAnnotation.typeName &&
197
- path.node.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
198
- path.node.typeAnnotation.typeAnnotation.typeName.name === typeName) {
199
- return true;
200
- }
201
- return false;
202
- })
203
- .forEach(path => {
204
- // Update the value if it matches the old value
205
- if (path.node.value &&
206
- path.node.value.type === 'StringLiteral' &&
207
- path.node.value.value === oldValue) {
208
- path.node.value.value = newValue;
209
- }
210
- });
211
- // 2. Find all assignments to variables of the specified type
212
- const variablesOfType = new Set();
213
- // First, collect all variables with the specified type
214
- root
215
- .find(j.VariableDeclarator)
216
- .filter(path => {
217
- if (path.node.id.type === 'Identifier' &&
218
- path.node.id.typeAnnotation?.typeAnnotation &&
219
- path.node.id.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
220
- path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
221
- path.node.id.typeAnnotation.typeAnnotation.typeName.name === typeName) {
222
- return true;
223
- }
224
- return false;
225
- })
226
- .forEach(path => {
227
- if (path.node.id.type === 'Identifier') {
228
- variablesOfType.add(path.node.id.name);
229
- // Also update the initial value if it matches
230
- if (path.node.init &&
231
- path.node.init.type === 'StringLiteral' &&
232
- path.node.init.value === oldValue) {
233
- path.node.init.value = newValue;
281
+ const tsPropertyValueTransformer = (source, root, j, typeName, oldValue, newValue) => {
282
+ if (source.includes(typeName)) {
283
+ root.find(j.ClassProperty)
284
+ .filter((path) => {
285
+ if (path.node.typeAnnotation?.typeAnnotation &&
286
+ path.node.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
287
+ path.node.typeAnnotation.typeAnnotation.typeName &&
288
+ path.node.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
289
+ path.node.typeAnnotation.typeAnnotation.typeName.name === typeName) {
290
+ return true;
234
291
  }
235
- }
236
- });
237
- // 3. Update literals in assignment expressions
238
- root
239
- .find(j.AssignmentExpression)
240
- .filter(path => {
241
- // Only process string literals with the old value
242
- return path.node.right.type === 'StringLiteral' &&
243
- path.node.right.value === oldValue;
244
- })
245
- .forEach(path => {
246
- // Update the value
247
- path.node.right.value = newValue;
248
- });
249
- // 4. Also look for string literals in attributes within JSX elements
250
- root
251
- .find(j.JSXAttribute, {
252
- value: {
253
- type: 'StringLiteral',
254
- value: oldValue
255
- }
256
- })
257
- .forEach(path => {
258
- if (path.node.value?.type === 'StringLiteral') {
259
- path.node.value.value = newValue;
260
- }
261
- });
292
+ return false;
293
+ })
294
+ .forEach((path) => {
295
+ if (path.node.value && path.node.value.type === 'StringLiteral' && path.node.value.value === oldValue) {
296
+ path.node.value.value = newValue;
297
+ }
298
+ });
299
+ root.find(j.VariableDeclarator)
300
+ .filter((path) => {
301
+ if (path.node.id.type === 'Identifier' &&
302
+ path.node.id.typeAnnotation?.typeAnnotation &&
303
+ path.node.id.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
304
+ path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
305
+ path.node.id.typeAnnotation.typeAnnotation.typeName.name === typeName) {
306
+ return true;
307
+ }
308
+ return false;
309
+ })
310
+ .forEach((path) => {
311
+ if (path.node.id.type === 'Identifier') {
312
+ if (path.node.init && path.node.init.type === 'StringLiteral' && path.node.init.value === oldValue) {
313
+ path.node.init.value = newValue;
314
+ }
315
+ }
316
+ });
317
+ root.find(j.AssignmentExpression)
318
+ .filter((path) => {
319
+ return path.node.right.type === 'StringLiteral' && path.node.right.value === oldValue;
320
+ })
321
+ .forEach((path) => {
322
+ path.node.right.value = newValue;
323
+ });
324
+ root.find(j.JSXAttribute, {
325
+ value: {
326
+ type: 'StringLiteral',
327
+ value: oldValue,
328
+ },
329
+ }).forEach((path) => {
330
+ if (path.node.value?.type === 'StringLiteral') {
331
+ path.node.value.value = newValue;
332
+ }
333
+ });
334
+ }
262
335
  };
263
336
  exports.tsPropertyValueTransformer = tsPropertyValueTransformer;
264
337
  const htmlAttributeValueTransformer = (fileInfo, tagName, attributeName, oldValue, newValue) => {
265
- // Read file content from fileInfo
266
338
  const fileContent = fileInfo.source;
267
- // Parse the HTML content
268
- const root = (0, node_html_parser_1.default)(fileContent);
269
- // Find all elements matching the tagName
339
+ const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
270
340
  const elements = root.querySelectorAll(tagName);
271
341
  let modified = false;
272
- // Process each element
273
342
  for (const element of elements) {
274
343
  // Handle static attributes (e.g., showText="overflow")
275
344
  const staticAttr = element.getAttribute(attributeName);
@@ -290,37 +359,35 @@ const htmlAttributeValueTransformer = (fileInfo, tagName, attributeName, oldValu
290
359
  }
291
360
  }
292
361
  }
293
- // Return modified content if changes were made
294
362
  if (modified) {
295
363
  const updatedContent = root.toString();
296
364
  return updatedContent;
297
365
  }
298
- // Return original content if no changes were made or if there was an error
299
366
  return fileContent;
300
367
  };
301
368
  exports.htmlAttributeValueTransformer = htmlAttributeValueTransformer;
302
369
  const htmlAttributeRemoval = (fileInfo, tagName, attributeName, propertyToRemove) => {
303
370
  const filePath = fileInfo.path;
304
371
  const fileContent = fileInfo.source;
305
- const root = (0, node_html_parser_1.default)(fileContent);
372
+ const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
306
373
  // Use the same logic as templateAttributeRemoval
307
374
  const elements = root.querySelectorAll(tagName);
308
375
  for (const element of elements) {
376
+ // If no propertyToRemove is specified, remove the entire attribute
377
+ if (!propertyToRemove) {
378
+ // Remove both bound and static attributes
379
+ element.removeAttribute(`[${attributeName}]`);
380
+ element.removeAttribute(attributeName);
381
+ continue;
382
+ }
309
383
  // Look for bound attribute (e.g., [scrollable]="...")
310
384
  const boundAttr = element.getAttribute(`[${attributeName}]`);
311
385
  if (boundAttr) {
312
- // Check if it's an object literal
313
386
  if (boundAttr.trim().startsWith('{') && boundAttr.trim().endsWith('}')) {
314
- // Process object literal like {mouseScrollSpeed: 10000}
315
387
  const objectLiteral = boundAttr.trim();
316
- // Build a regex that matches the property and its value
317
- // This handles various formats like {prop: value}, { prop: value }, etc.
318
388
  const propRegex = new RegExp(`\\s*${propertyToRemove}\\s*:\\s*[^,}]+\\s*(,\\s*)?`, 'g');
319
- // Remove the property and any trailing comma
320
389
  let newObjectLiteral = objectLiteral.replace(propRegex, '');
321
- // Fix syntax if we removed the last property with trailing comma
322
390
  newObjectLiteral = newObjectLiteral.replace(/,\s*}$/, '}');
323
- // If the object is now empty, remove the attribute completely
324
391
  if (newObjectLiteral === '{}') {
325
392
  element.removeAttribute(`[${attributeName}]`);
326
393
  }
@@ -328,44 +395,29 @@ const htmlAttributeRemoval = (fileInfo, tagName, attributeName, propertyToRemove
328
395
  element.setAttribute(`[${attributeName}]`, newObjectLiteral);
329
396
  }
330
397
  }
331
- // Check if it's a variable reference to an object
332
398
  else {
333
- // For variable references, we can't modify them in the template
334
- // We should warn the user or handle this case specially
335
399
  console.warn(`Cannot remove property from variable reference: ${boundAttr} in file ${filePath}`);
336
400
  }
337
401
  }
338
402
  }
339
- // Return the modified HTML content
340
403
  return root.toString();
341
404
  };
342
405
  exports.htmlAttributeRemoval = htmlAttributeRemoval;
343
- /**
344
- * Removes a specified property from an object binding in HTML templates
345
- *
346
- * @param root - The HTML root element
347
- * @param tagName - The tag to search for (e.g., 'kendo-tabstrip')
348
- * @param attributeName - The attribute containing the object binding (e.g., 'scrollable')
349
- * @param propertyToRemove - The property to remove from the object (e.g., 'mouseScrollSpeed')
350
- */
351
406
  const templateAttributeRemoval = (root, tagName, attributeName, propertyToRemove) => {
352
407
  const elements = root.querySelectorAll(tagName);
353
408
  for (const element of elements) {
354
- // Look for bound attribute (e.g., [scrollable]="...")
409
+ if (!propertyToRemove) {
410
+ element.removeAttribute(`[${attributeName}]`);
411
+ element.removeAttribute(attributeName);
412
+ continue;
413
+ }
355
414
  const boundAttr = element.getAttribute(`[${attributeName}]`);
356
415
  if (boundAttr) {
357
- // Check if it's an object literal
358
416
  if (boundAttr.trim().startsWith('{') && boundAttr.trim().endsWith('}')) {
359
- // Process object literal like {mouseScrollSpeed: 10000}
360
417
  const objectLiteral = boundAttr.trim();
361
- // Build a regex that matches the property and its value
362
- // This handles various formats like {prop: value}, { prop: value }, etc.
363
418
  const propRegex = new RegExp(`\\s*${propertyToRemove}\\s*:\\s*[^,}]+\\s*(,\\s*)?`, 'g');
364
- // Remove the property and any trailing comma
365
419
  let newObjectLiteral = objectLiteral.replace(propRegex, '');
366
- // Fix syntax if we removed the last property with trailing comma
367
420
  newObjectLiteral = newObjectLiteral.replace(/,\s*}$/, '}');
368
- // If the object is now empty, remove the attribute completely
369
421
  if (newObjectLiteral === '{}') {
370
422
  element.removeAttribute(`[${attributeName}]`);
371
423
  }
@@ -373,181 +425,287 @@ const templateAttributeRemoval = (root, tagName, attributeName, propertyToRemove
373
425
  element.setAttribute(`[${attributeName}]`, newObjectLiteral);
374
426
  }
375
427
  }
376
- // Check if it's a variable reference to an object
377
428
  else {
378
- // For variable references, we can't modify them in the template
379
- // We should warn the user or handle this case specially
380
429
  console.warn(`Cannot remove property from variable reference: ${boundAttr}`);
381
430
  }
382
431
  }
383
432
  }
384
433
  };
385
434
  exports.templateAttributeRemoval = templateAttributeRemoval;
386
- /**
387
- * Removes a property from object literals of a specified type
388
- *
389
- * @param root - The AST root
390
- * @param j - The JSCodeshift instance
391
- * @param typeName - The type to target (e.g., 'TabStripScrollableSettings')
392
- * @param propertyToRemove - The property to remove (e.g., 'mouseScrollSpeed')
393
- */
394
- function tsPropertyRemoval(rootSource, j, typeName, propertyName) {
395
- // Find class properties that have the specified type
396
- rootSource
397
- .find(j.ClassProperty, {
398
- typeAnnotation: {
435
+ function tsPropertyRemoval(source, rootSource, j, typeName, propertyName) {
436
+ if (source.includes(typeName)) {
437
+ rootSource
438
+ .find(j.ClassProperty, {
399
439
  typeAnnotation: {
400
- typeName: {
401
- name: typeName
440
+ typeAnnotation: {
441
+ typeName: {
442
+ name: typeName,
443
+ },
444
+ },
445
+ },
446
+ })
447
+ .forEach((path) => {
448
+ if (path.node.value && path.node.value.type === 'ObjectExpression') {
449
+ const properties = path.node.value.properties;
450
+ const propIndex = properties.findIndex((p) => p.type === 'ObjectProperty' &&
451
+ p.key &&
452
+ p.key.type === 'Identifier' &&
453
+ p.key.name === propertyName);
454
+ if (propIndex !== -1) {
455
+ if (properties.length === 1) {
456
+ j(path).remove();
457
+ }
458
+ else {
459
+ properties.splice(propIndex, 1);
460
+ }
402
461
  }
403
462
  }
463
+ });
464
+ rootSource
465
+ .find(j.AssignmentExpression, {
466
+ left: {
467
+ type: 'MemberExpression',
468
+ object: {
469
+ type: 'MemberExpression',
470
+ },
471
+ property: {
472
+ name: propertyName,
473
+ },
474
+ },
475
+ })
476
+ .forEach((path) => {
477
+ j(path).remove();
478
+ });
479
+ return rootSource;
480
+ }
481
+ }
482
+ const tsComponentPropertyRemoval = (source, root, j, componentType, componentProperty, propertyToRemove) => {
483
+ if (source.includes(componentType)) {
484
+ // If no propertyToRemove is specified, remove the entire componentProperty
485
+ if (!propertyToRemove) {
486
+ // Handle direct property assignments like: foo.scrollable = value;
487
+ root.find(j.AssignmentExpression)
488
+ .filter((path) => {
489
+ const { left } = path.value;
490
+ // Check if this assigns to component.componentProperty
491
+ if (left &&
492
+ left.type === 'MemberExpression' &&
493
+ left.property &&
494
+ left.property.name === componentProperty) {
495
+ // Check if the base object is our component type
496
+ return isComponentTypeMatch(root, j, left.object, componentType);
497
+ }
498
+ return false;
499
+ })
500
+ .forEach((path) => {
501
+ // Remove the entire statement
502
+ j(path).closest(j.ExpressionStatement).remove();
503
+ });
504
+ return root;
404
505
  }
405
- })
406
- .forEach(path => {
407
- // Check if there's an object literal initializer
408
- if (path.node.value && path.node.value.type === 'ObjectExpression') {
409
- const properties = path.node.value.properties;
410
- // Find the property we want to remove - safely handle different property types
411
- const propIndex = properties.findIndex((p) => p.type === 'ObjectProperty' &&
506
+ // CASE 1: Handle direct property assignments like: foo.scrollable.mouseScrollSpeed = 3000;
507
+ root.find(j.AssignmentExpression)
508
+ .filter((path) => {
509
+ const { left } = path.value;
510
+ // Check if this is a member expression assignment
511
+ if (left && left.type === 'MemberExpression') {
512
+ // Check if we're accessing the property to remove
513
+ if (left.property && left.property.name === propertyToRemove) {
514
+ // Check if we're accessing it from component.componentProperty
515
+ const obj = left.object;
516
+ if (obj &&
517
+ obj.type === 'MemberExpression' &&
518
+ obj.property &&
519
+ obj.property.name === componentProperty) {
520
+ // Now check if the base object is our component type
521
+ return isComponentTypeMatch(root, j, obj.object, componentType);
522
+ }
523
+ }
524
+ }
525
+ return false;
526
+ })
527
+ .forEach((path) => {
528
+ // Remove the entire statement
529
+ j(path).closest(j.ExpressionStatement).remove();
530
+ });
531
+ // CASE 2 & 3: Handle object assignments like: foo.scrollable = { mouseScrollSpeed: 3000, ... };
532
+ root.find(j.AssignmentExpression)
533
+ .filter((path) => {
534
+ const { left, right } = path.value;
535
+ // Check if this assigns to component.componentProperty
536
+ if (left &&
537
+ left.type === 'MemberExpression' &&
538
+ left.property &&
539
+ left.property.name === componentProperty &&
540
+ right &&
541
+ right.type === 'ObjectExpression') {
542
+ // Check if the base object is our component type
543
+ return isComponentTypeMatch(root, j, left.object, componentType);
544
+ }
545
+ return false;
546
+ })
547
+ .forEach((path) => {
548
+ const properties = path.value.right.properties;
549
+ // Find the property we want to remove
550
+ const propIndex = properties.findIndex((p) => p &&
551
+ p.type === 'ObjectProperty' &&
412
552
  p.key &&
413
553
  p.key.type === 'Identifier' &&
414
- p.key.name === propertyName);
554
+ p.key.name === propertyToRemove);
415
555
  if (propIndex !== -1) {
416
- // If property exists, remove it
417
- // Case 1: If it's the only property, remove the entire class property
556
+ // Case 2: If it's the only property, remove the entire statement
418
557
  if (properties.length === 1) {
419
- j(path).remove();
558
+ j(path).closest(j.ExpressionStatement).remove();
420
559
  }
421
- // Case 2: If there are other properties, just remove this one property
560
+ // Case 3: If there are other properties, just remove this one property
422
561
  else {
423
562
  properties.splice(propIndex, 1);
424
563
  }
425
564
  }
426
- }
427
- });
428
- // Also handle property assignments (e.g., in methods like ngOnInit)
429
- rootSource
430
- .find(j.AssignmentExpression, {
431
- left: {
432
- type: 'MemberExpression',
433
- object: {
434
- type: 'MemberExpression'
435
- },
436
- property: {
437
- name: propertyName
438
- }
439
- }
440
- })
441
- .forEach(path => {
442
- j(path).remove();
443
- });
444
- return rootSource;
445
- }
446
- /**
447
- * Removes assignments to a specific nested property of a component
448
- *
449
- * @param root - The AST root
450
- * @param j - The JSCodeshift instance
451
- * @param componentType - The component type to target (e.g., 'TabStripComponent')
452
- * @param componentProperty - The component property (e.g., 'scrollable')
453
- * @param propertyToRemove - The nested property to remove assignments to (e.g., 'mouseScrollSpeed')
454
- */
455
- const tsComponentPropertyRemoval = (root, j, componentType, componentProperty, propertyToRemove) => {
456
- // CASE 1: Handle direct property assignments like: foo.scrollable.mouseScrollSpeed = 3000;
457
- root
458
- .find(j.AssignmentExpression)
459
- .filter((path) => {
460
- const { left } = path.value;
461
- // Check if this is a member expression assignment
462
- if (left && left.type === 'MemberExpression') {
463
- // Check if we're accessing the property to remove
464
- if (left.property && left.property.name === propertyToRemove) {
465
- // Check if we're accessing it from component.componentProperty
466
- const obj = left.object;
467
- if (obj && obj.type === 'MemberExpression' &&
468
- obj.property && obj.property.name === componentProperty) {
469
- // Now check if the base object is our component type
470
- return isComponentTypeMatch(root, j, obj.object, componentType);
471
- }
472
- }
473
- }
474
- return false;
475
- })
476
- .forEach((path) => {
477
- // Remove the entire statement
478
- j(path).closest(j.ExpressionStatement).remove();
479
- });
480
- // CASE 2 & 3: Handle object assignments like: foo.scrollable = { mouseScrollSpeed: 3000, ... };
481
- root
482
- .find(j.AssignmentExpression)
483
- .filter((path) => {
484
- const { left, right } = path.value;
485
- // Check if this assigns to component.componentProperty
486
- if (left && left.type === 'MemberExpression' &&
487
- left.property && left.property.name === componentProperty &&
488
- right && right.type === 'ObjectExpression') {
489
- // Check if the base object is our component type
490
- return isComponentTypeMatch(root, j, left.object, componentType);
491
- }
492
- return false;
493
- })
494
- .forEach((path) => {
495
- const properties = path.value.right.properties;
496
- // Find the property we want to remove
497
- const propIndex = properties.findIndex((p) => p && p.type === 'ObjectProperty' &&
498
- p.key && p.key.type === 'Identifier' &&
499
- p.key.name === propertyToRemove);
500
- if (propIndex !== -1) {
501
- // Case 2: If it's the only property, remove the entire statement
502
- if (properties.length === 1) {
503
- j(path).closest(j.ExpressionStatement).remove();
504
- }
505
- // Case 3: If there are other properties, just remove this one property
506
- else {
507
- properties.splice(propIndex, 1);
508
- }
509
- }
510
- });
511
- return root;
565
+ });
566
+ return root;
567
+ }
512
568
  };
513
569
  exports.tsComponentPropertyRemoval = tsComponentPropertyRemoval;
514
570
  // Helper function to check if a node is a component of the specified type
515
571
  function isComponentTypeMatch(root, j, node, componentType) {
516
572
  if (!node)
517
573
  return false;
518
- // Case 1: Direct match for 'this.propertyName'
519
574
  if (node.type === 'ThisExpression') {
520
- return true; // Assuming 'this' refers to the component class
575
+ return true;
521
576
  }
522
- // Case 2: Function parameter
523
577
  if (node.type === 'Identifier') {
524
578
  const paramName = node.name;
525
- // Check function parameters
526
- return root
527
- .find(j.Function)
528
- .some(path => {
529
- return path.node.params && path.node.params.some((param) => param.type === 'Identifier' &&
530
- param.name === paramName &&
531
- param.typeAnnotation?.typeAnnotation?.typeName?.name === componentType);
579
+ return root.find(j.Function).some((path) => {
580
+ return (path.node.params &&
581
+ path.node.params.some((param) => param.type === 'Identifier' &&
582
+ param.name === paramName &&
583
+ param.typeAnnotation?.typeAnnotation?.typeName?.name === componentType));
532
584
  });
533
585
  }
534
- // Case 3: Member expression (obj.prop)
535
586
  if (node.type === 'MemberExpression') {
536
- // This would need more complex logic to determine if the object is of the right type
537
- // For now, we can check if it's a property that has been declared with the right type
538
587
  if (node.object.type === 'ThisExpression' && node.property.type === 'Identifier') {
539
588
  const propName = node.property.name;
540
- return root
589
+ return (root
541
590
  .find(j.ClassProperty, {
542
591
  key: { name: propName },
543
592
  typeAnnotation: {
544
593
  typeAnnotation: {
545
- typeName: { name: componentType }
546
- }
547
- }
594
+ typeName: { name: componentType },
595
+ },
596
+ },
548
597
  })
549
- .size() > 0;
598
+ .size() > 0);
550
599
  }
551
600
  }
552
601
  return false;
553
602
  }
603
+ const tsInterfaceTransformer = (fileInfo, rootSource, j, packageName, interfaceName, newName) => {
604
+ const source = fileInfo.source;
605
+ if (source.includes(interfaceName)) {
606
+ let isImportedFromKendoListbox = false;
607
+ rootSource.find(j.ImportDeclaration).forEach((path) => {
608
+ if (path.node.source &&
609
+ path.node.source.value === packageName &&
610
+ path.node.specifiers) {
611
+ path.node.specifiers.forEach((specifier) => {
612
+ if (specifier.type === 'ImportSpecifier' &&
613
+ specifier.imported.type === 'Identifier' &&
614
+ specifier.imported.name === interfaceName) {
615
+ isImportedFromKendoListbox = true;
616
+ specifier.imported.name = newName;
617
+ }
618
+ });
619
+ }
620
+ });
621
+ if (!isImportedFromKendoListbox) {
622
+ return;
623
+ }
624
+ rootSource.find(j.ClassProperty).forEach((path) => {
625
+ if (path.node.typeAnnotation &&
626
+ path.node.typeAnnotation.typeAnnotation &&
627
+ path.node.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
628
+ path.node.typeAnnotation.typeAnnotation.typeName &&
629
+ path.node.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
630
+ path.node.typeAnnotation.typeAnnotation.typeName.name === interfaceName) {
631
+ path.node.typeAnnotation.typeAnnotation.typeName.name = newName;
632
+ }
633
+ });
634
+ rootSource.find(j.VariableDeclarator).forEach((path) => {
635
+ if (path.node.id.type === 'Identifier' &&
636
+ path.node.id.typeAnnotation &&
637
+ path.node.id.typeAnnotation.typeAnnotation &&
638
+ path.node.id.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
639
+ path.node.id.typeAnnotation.typeAnnotation.typeName &&
640
+ path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
641
+ path.node.id.typeAnnotation.typeAnnotation.typeName.name === interfaceName) {
642
+ path.node.id.typeAnnotation.typeAnnotation.typeName.name = newName;
643
+ }
644
+ });
645
+ rootSource.find(j.FunctionDeclaration).forEach((path) => {
646
+ if (path.node.params) {
647
+ path.node.params.forEach((param) => {
648
+ if (param.type === 'Identifier' &&
649
+ param.typeAnnotation &&
650
+ param.typeAnnotation.typeAnnotation &&
651
+ param.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
652
+ param.typeAnnotation.typeAnnotation.typeName &&
653
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
654
+ param.typeAnnotation.typeAnnotation.typeName.name === interfaceName) {
655
+ param.typeAnnotation.typeAnnotation.typeName.name = newName;
656
+ }
657
+ });
658
+ }
659
+ });
660
+ rootSource.find(j.ArrowFunctionExpression).forEach((path) => {
661
+ if (path.node.params) {
662
+ path.node.params.forEach((param) => {
663
+ if (param.type === 'Identifier' &&
664
+ param.typeAnnotation &&
665
+ param.typeAnnotation.typeAnnotation &&
666
+ param.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
667
+ param.typeAnnotation.typeAnnotation.typeName &&
668
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
669
+ param.typeAnnotation.typeAnnotation.typeName.name === interfaceName) {
670
+ param.typeAnnotation.typeAnnotation.typeName.name = newName;
671
+ }
672
+ });
673
+ }
674
+ });
675
+ rootSource.find(j.ClassMethod).forEach((path) => {
676
+ if (path.node.params) {
677
+ path.node.params.forEach((param) => {
678
+ if (param.type === 'Identifier' &&
679
+ param.typeAnnotation &&
680
+ param.typeAnnotation.typeAnnotation &&
681
+ param.typeAnnotation.typeAnnotation.type === 'TSTypeReference' &&
682
+ param.typeAnnotation.typeAnnotation.typeName &&
683
+ param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
684
+ param.typeAnnotation.typeAnnotation.typeName.name === interfaceName) {
685
+ param.typeAnnotation.typeAnnotation.typeName.name = newName;
686
+ }
687
+ });
688
+ }
689
+ });
690
+ rootSource.find(j.Function).forEach((path) => {
691
+ if (path.node.returnType &&
692
+ path.node.returnType.typeAnnotation &&
693
+ path.node.returnType.typeAnnotation.type === 'TSTypeReference' &&
694
+ path.node.returnType.typeAnnotation.typeName &&
695
+ path.node.returnType.typeAnnotation.typeName.type === 'Identifier' &&
696
+ path.node.returnType.typeAnnotation.typeName.name === interfaceName) {
697
+ path.node.returnType.typeAnnotation.typeName.name = newName;
698
+ }
699
+ });
700
+ rootSource.find(j.TSAsExpression).forEach((path) => {
701
+ if (path.node.typeAnnotation &&
702
+ path.node.typeAnnotation.type === 'TSTypeReference' &&
703
+ path.node.typeAnnotation.typeName &&
704
+ path.node.typeAnnotation.typeName.type === 'Identifier' &&
705
+ path.node.typeAnnotation.typeName.name === interfaceName) {
706
+ path.node.typeAnnotation.typeName.name = newName;
707
+ }
708
+ });
709
+ }
710
+ };
711
+ exports.tsInterfaceTransformer = tsInterfaceTransformer;