@progress/kendo-angular-listbox 21.0.0-develop.16 → 21.0.0-develop.18
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/codemods/template-transformer/index.js +93 -0
- package/codemods/utils.js +711 -0
- package/codemods/v21/listbox-actionclick.js +52 -0
- package/codemods/v21/listbox-selectedindex.js +125 -0
- package/codemods/v21/listbox-toolbar.js +14 -0
- package/esm2022/package-metadata.mjs +2 -2
- package/fesm2022/progress-kendo-angular-listbox.mjs +2 -2
- package/package.json +33 -7
- package/schematics/ngAdd/index.js +4 -4
|
@@ -0,0 +1,93 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.templateTransformer = templateTransformer;
|
|
8
|
+
const node_html_parser_1 = require("node-html-parser");
|
|
9
|
+
function templateTransformer(root, j, ...processFns) {
|
|
10
|
+
root
|
|
11
|
+
.find(j.ClassDeclaration)
|
|
12
|
+
.forEach(classPath => {
|
|
13
|
+
// Skip if no decorators
|
|
14
|
+
const classNode = classPath.node;
|
|
15
|
+
if (!classNode.decorators || !classNode.decorators.length)
|
|
16
|
+
return;
|
|
17
|
+
// Find Component decorator
|
|
18
|
+
const componentDecorator = classNode.decorators.find((decorator) => {
|
|
19
|
+
if (decorator.expression && decorator.expression.type === 'CallExpression') {
|
|
20
|
+
const callee = decorator.expression.callee;
|
|
21
|
+
// Handle direct Component identifier
|
|
22
|
+
if (callee.type === 'Identifier' && callee.name === 'Component') {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
// Handle angular.core.Component or similar
|
|
26
|
+
if (callee.type === 'MemberExpression' &&
|
|
27
|
+
callee.property &&
|
|
28
|
+
callee.property.type === 'Identifier' &&
|
|
29
|
+
callee.property.name === 'Component') {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
});
|
|
35
|
+
if (!componentDecorator || !componentDecorator.expression)
|
|
36
|
+
return;
|
|
37
|
+
const expression = componentDecorator.expression;
|
|
38
|
+
if (expression.type !== 'CallExpression' || !expression.arguments.length)
|
|
39
|
+
return;
|
|
40
|
+
const componentOptions = expression.arguments[0];
|
|
41
|
+
if (componentOptions.type !== 'ObjectExpression')
|
|
42
|
+
return;
|
|
43
|
+
// Find template and templateUrl properties
|
|
44
|
+
const props = componentOptions.properties || [];
|
|
45
|
+
const templateProp = props.find((prop) => (prop.key.type === 'Identifier' && prop.key.name === 'template') ||
|
|
46
|
+
(prop.key.type === 'StringLiteral' && prop.key.value === 'template'));
|
|
47
|
+
// const templateUrlProp = props.find((prop: any) =>
|
|
48
|
+
// (prop.key.type === 'Identifier' && prop.key.name === 'templateUrl') ||
|
|
49
|
+
// (prop.key.type === 'StringLiteral' && prop.key.value === 'templateUrl')
|
|
50
|
+
// );
|
|
51
|
+
// Process inline template
|
|
52
|
+
if (templateProp) {
|
|
53
|
+
// Extract template based on node type
|
|
54
|
+
let originalTemplate;
|
|
55
|
+
if (templateProp.value.type === 'StringLiteral' || templateProp.value.type === 'Literal') {
|
|
56
|
+
originalTemplate = templateProp.value.value;
|
|
57
|
+
}
|
|
58
|
+
else if (templateProp.value.type === 'TemplateLiteral') {
|
|
59
|
+
// For template literals, join quasis
|
|
60
|
+
if (templateProp.value.quasis && templateProp.value.quasis.length) {
|
|
61
|
+
originalTemplate = templateProp.value.quasis
|
|
62
|
+
.map((q) => q.value.cooked || q.value.raw)
|
|
63
|
+
.join('');
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.warn('Could not process TemplateLiteral properly');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.warn(`Unsupported template type: ${templateProp.value.type}`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const root = (0, node_html_parser_1.parse)(originalTemplate);
|
|
75
|
+
processFns.forEach(fn => {
|
|
76
|
+
fn(root);
|
|
77
|
+
});
|
|
78
|
+
// Transform template using Angular compiler
|
|
79
|
+
const transformedTemplate = root.toString();
|
|
80
|
+
if (transformedTemplate !== originalTemplate) {
|
|
81
|
+
// Update template property
|
|
82
|
+
if (templateProp.value.type === 'TemplateLiteral') {
|
|
83
|
+
// For template literals, create a new template literal
|
|
84
|
+
templateProp.value = j.templateLiteral([j.templateElement({ cooked: transformedTemplate, raw: transformedTemplate }, true)], []);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// For string literals, update the value
|
|
88
|
+
templateProp.value.value = transformedTemplate;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
@@ -0,0 +1,711 @@
|
|
|
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.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;
|
|
12
|
+
exports.tsPropertyRemoval = tsPropertyRemoval;
|
|
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;
|
|
36
|
+
const templateStaticAttributeTransformer = (root, tagName, attributeName, newAttributeName) => {
|
|
37
|
+
const elements = Array.from(root.getElementsByTagName(tagName)) || [];
|
|
38
|
+
for (const element of elements) {
|
|
39
|
+
// Handle static attributes like title="foo"
|
|
40
|
+
const staticAttr = element.getAttribute(attributeName);
|
|
41
|
+
if (staticAttr) {
|
|
42
|
+
element.setAttribute(newAttributeName, staticAttr);
|
|
43
|
+
element.removeAttribute(attributeName);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
exports.templateStaticAttributeTransformer = templateStaticAttributeTransformer;
|
|
48
|
+
const templateBoundAttributeTransformer = (root, tagName, attributeName, newAttributeName, valueProperty) => {
|
|
49
|
+
const elements = Array.from(root.getElementsByTagName(tagName)) || [];
|
|
50
|
+
for (const element of elements) {
|
|
51
|
+
// Handle bound attributes like [title]="foo" or [title]="'foo'"
|
|
52
|
+
const boundAttr = element.getAttribute(`[${attributeName}]`);
|
|
53
|
+
if (boundAttr) {
|
|
54
|
+
const newValue = valueProperty ? `${boundAttr}.${valueProperty}` : boundAttr;
|
|
55
|
+
element.setAttribute(`[${newAttributeName}]`, newValue);
|
|
56
|
+
element.removeAttribute(`[${attributeName}]`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.templateBoundAttributeTransformer = templateBoundAttributeTransformer;
|
|
61
|
+
const templateAttributeTransformer = (root, tagName, attributeName, newAttributeName) => {
|
|
62
|
+
(0, exports.templateBoundAttributeTransformer)(root, tagName, attributeName, newAttributeName);
|
|
63
|
+
(0, exports.templateStaticAttributeTransformer)(root, tagName, attributeName, newAttributeName);
|
|
64
|
+
};
|
|
65
|
+
exports.templateAttributeTransformer = templateAttributeTransformer;
|
|
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, {
|
|
72
|
+
typeAnnotation: {
|
|
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);
|
|
82
|
+
}
|
|
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;
|
|
152
|
+
}
|
|
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
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
exports.tsPropertyTransformer = tsPropertyTransformer;
|
|
198
|
+
const htmlStaticAttributeTransformer = (fileInfo, tagName, oldName, newName) => {
|
|
199
|
+
const fileContent = fileInfo.source;
|
|
200
|
+
const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
|
|
201
|
+
let modified = false;
|
|
202
|
+
const elements = Array.from(root.querySelectorAll(tagName));
|
|
203
|
+
for (const element of elements) {
|
|
204
|
+
const staticAttr = element.getAttribute(oldName);
|
|
205
|
+
if (staticAttr) {
|
|
206
|
+
element.removeAttribute(oldName);
|
|
207
|
+
element.setAttribute(newName, staticAttr);
|
|
208
|
+
modified = true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (modified) {
|
|
212
|
+
return root.toString();
|
|
213
|
+
}
|
|
214
|
+
return fileContent;
|
|
215
|
+
};
|
|
216
|
+
exports.htmlStaticAttributeTransformer = htmlStaticAttributeTransformer;
|
|
217
|
+
const htmlBoundAttributeTransformer = (fileInfo, tagName, oldName, newName, valueProperty) => {
|
|
218
|
+
const fileContent = fileInfo.source;
|
|
219
|
+
const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
|
|
220
|
+
let modified = false;
|
|
221
|
+
const elements = Array.from(root.querySelectorAll(tagName));
|
|
222
|
+
for (const element of elements) {
|
|
223
|
+
const boundAttr = element.getAttribute(`[${oldName}]`);
|
|
224
|
+
if (boundAttr) {
|
|
225
|
+
element.removeAttribute(`[${oldName}]`);
|
|
226
|
+
// If valueProperty is provided, append it to the bound value
|
|
227
|
+
const newValue = valueProperty ? `${boundAttr}.${valueProperty}` : boundAttr;
|
|
228
|
+
element.setAttribute(`[${newName}]`, newValue);
|
|
229
|
+
modified = true;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (modified) {
|
|
233
|
+
return root.toString();
|
|
234
|
+
}
|
|
235
|
+
return fileContent;
|
|
236
|
+
};
|
|
237
|
+
exports.htmlBoundAttributeTransformer = htmlBoundAttributeTransformer;
|
|
238
|
+
const htmlAttributeTransformer = (fileInfo, tagName, oldName, newName) => {
|
|
239
|
+
let content = (0, exports.htmlBoundAttributeTransformer)(fileInfo, tagName, oldName, newName);
|
|
240
|
+
content = (0, exports.htmlStaticAttributeTransformer)({ path: fileInfo.path, source: content }, tagName, oldName, newName);
|
|
241
|
+
return content;
|
|
242
|
+
};
|
|
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;
|
|
264
|
+
const templateAttributeValueTransformer = (root, tagName, attributeName, oldAttributeValue, newAttributeValue) => {
|
|
265
|
+
const elements = Array.from(root.getElementsByTagName(tagName)) || [];
|
|
266
|
+
for (const element of elements) {
|
|
267
|
+
// Handle bound attributes (e.g., [showText]="'overflow'")
|
|
268
|
+
const boundAttr = element.getAttribute(`[${attributeName}]`);
|
|
269
|
+
if (boundAttr === `'${oldAttributeValue}'`) {
|
|
270
|
+
// For bound literals like [showText]="'overflow'" or [showText]="\"overflow\""
|
|
271
|
+
element.setAttribute(`[${attributeName}]`, boundAttr.replace(oldAttributeValue, newAttributeValue));
|
|
272
|
+
}
|
|
273
|
+
// Handle static attributes like title="foo"
|
|
274
|
+
const staticAttrValue = element.getAttribute(attributeName);
|
|
275
|
+
if (staticAttrValue === oldAttributeValue) {
|
|
276
|
+
element.setAttribute(attributeName, newAttributeValue);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
exports.templateAttributeValueTransformer = templateAttributeValueTransformer;
|
|
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;
|
|
291
|
+
}
|
|
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
|
+
}
|
|
335
|
+
};
|
|
336
|
+
exports.tsPropertyValueTransformer = tsPropertyValueTransformer;
|
|
337
|
+
const htmlAttributeValueTransformer = (fileInfo, tagName, attributeName, oldValue, newValue) => {
|
|
338
|
+
const fileContent = fileInfo.source;
|
|
339
|
+
const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
|
|
340
|
+
const elements = root.querySelectorAll(tagName);
|
|
341
|
+
let modified = false;
|
|
342
|
+
for (const element of elements) {
|
|
343
|
+
// Handle static attributes (e.g., showText="overflow")
|
|
344
|
+
const staticAttr = element.getAttribute(attributeName);
|
|
345
|
+
if (staticAttr === oldValue) {
|
|
346
|
+
element.setAttribute(attributeName, newValue);
|
|
347
|
+
modified = true;
|
|
348
|
+
console.log(`Modified static attribute ${attributeName} from "${oldValue}" to "${newValue}" in element:`, element.toString().substring(0, 100));
|
|
349
|
+
}
|
|
350
|
+
// Handle bound attributes (e.g., [showText]="overflow")
|
|
351
|
+
const boundAttr = element.getAttribute(`[${attributeName}]`);
|
|
352
|
+
if (boundAttr) {
|
|
353
|
+
// For bound literals like [showText]="'overflow'" or [showText]="\"overflow\""
|
|
354
|
+
if (boundAttr === `'${oldValue}'` || boundAttr === `"${oldValue}"`) {
|
|
355
|
+
const updatedValue = boundAttr.replace(oldValue, newValue);
|
|
356
|
+
element.setAttribute(`[${attributeName}]`, updatedValue);
|
|
357
|
+
modified = true;
|
|
358
|
+
console.log(`Modified bound attribute [${attributeName}] from "${boundAttr}" to "${updatedValue}" in element:`, element.toString().substring(0, 100));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (modified) {
|
|
363
|
+
const updatedContent = root.toString();
|
|
364
|
+
return updatedContent;
|
|
365
|
+
}
|
|
366
|
+
return fileContent;
|
|
367
|
+
};
|
|
368
|
+
exports.htmlAttributeValueTransformer = htmlAttributeValueTransformer;
|
|
369
|
+
const htmlAttributeRemoval = (fileInfo, tagName, attributeName, propertyToRemove) => {
|
|
370
|
+
const filePath = fileInfo.path;
|
|
371
|
+
const fileContent = fileInfo.source;
|
|
372
|
+
const root = (0, node_html_parser_1.default)(fileContent, { comment: true, blockTextElements: exports.blockTextElements });
|
|
373
|
+
// Use the same logic as templateAttributeRemoval
|
|
374
|
+
const elements = root.querySelectorAll(tagName);
|
|
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
|
+
}
|
|
383
|
+
// Look for bound attribute (e.g., [scrollable]="...")
|
|
384
|
+
const boundAttr = element.getAttribute(`[${attributeName}]`);
|
|
385
|
+
if (boundAttr) {
|
|
386
|
+
if (boundAttr.trim().startsWith('{') && boundAttr.trim().endsWith('}')) {
|
|
387
|
+
const objectLiteral = boundAttr.trim();
|
|
388
|
+
const propRegex = new RegExp(`\\s*${propertyToRemove}\\s*:\\s*[^,}]+\\s*(,\\s*)?`, 'g');
|
|
389
|
+
let newObjectLiteral = objectLiteral.replace(propRegex, '');
|
|
390
|
+
newObjectLiteral = newObjectLiteral.replace(/,\s*}$/, '}');
|
|
391
|
+
if (newObjectLiteral === '{}') {
|
|
392
|
+
element.removeAttribute(`[${attributeName}]`);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
element.setAttribute(`[${attributeName}]`, newObjectLiteral);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
console.warn(`Cannot remove property from variable reference: ${boundAttr} in file ${filePath}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return root.toString();
|
|
404
|
+
};
|
|
405
|
+
exports.htmlAttributeRemoval = htmlAttributeRemoval;
|
|
406
|
+
const templateAttributeRemoval = (root, tagName, attributeName, propertyToRemove) => {
|
|
407
|
+
const elements = root.querySelectorAll(tagName);
|
|
408
|
+
for (const element of elements) {
|
|
409
|
+
if (!propertyToRemove) {
|
|
410
|
+
element.removeAttribute(`[${attributeName}]`);
|
|
411
|
+
element.removeAttribute(attributeName);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
const boundAttr = element.getAttribute(`[${attributeName}]`);
|
|
415
|
+
if (boundAttr) {
|
|
416
|
+
if (boundAttr.trim().startsWith('{') && boundAttr.trim().endsWith('}')) {
|
|
417
|
+
const objectLiteral = boundAttr.trim();
|
|
418
|
+
const propRegex = new RegExp(`\\s*${propertyToRemove}\\s*:\\s*[^,}]+\\s*(,\\s*)?`, 'g');
|
|
419
|
+
let newObjectLiteral = objectLiteral.replace(propRegex, '');
|
|
420
|
+
newObjectLiteral = newObjectLiteral.replace(/,\s*}$/, '}');
|
|
421
|
+
if (newObjectLiteral === '{}') {
|
|
422
|
+
element.removeAttribute(`[${attributeName}]`);
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
element.setAttribute(`[${attributeName}]`, newObjectLiteral);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
console.warn(`Cannot remove property from variable reference: ${boundAttr}`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
exports.templateAttributeRemoval = templateAttributeRemoval;
|
|
435
|
+
function tsPropertyRemoval(source, rootSource, j, typeName, propertyName) {
|
|
436
|
+
if (source.includes(typeName)) {
|
|
437
|
+
rootSource
|
|
438
|
+
.find(j.ClassProperty, {
|
|
439
|
+
typeAnnotation: {
|
|
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
|
+
}
|
|
461
|
+
}
|
|
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;
|
|
505
|
+
}
|
|
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' &&
|
|
552
|
+
p.key &&
|
|
553
|
+
p.key.type === 'Identifier' &&
|
|
554
|
+
p.key.name === propertyToRemove);
|
|
555
|
+
if (propIndex !== -1) {
|
|
556
|
+
// Case 2: If it's the only property, remove the entire statement
|
|
557
|
+
if (properties.length === 1) {
|
|
558
|
+
j(path).closest(j.ExpressionStatement).remove();
|
|
559
|
+
}
|
|
560
|
+
// Case 3: If there are other properties, just remove this one property
|
|
561
|
+
else {
|
|
562
|
+
properties.splice(propIndex, 1);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
return root;
|
|
567
|
+
}
|
|
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
|
+
if (node.type === 'ThisExpression') {
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
if (node.type === 'Identifier') {
|
|
578
|
+
const paramName = node.name;
|
|
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));
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
if (node.type === 'MemberExpression') {
|
|
587
|
+
if (node.object.type === 'ThisExpression' && node.property.type === 'Identifier') {
|
|
588
|
+
const propName = node.property.name;
|
|
589
|
+
return (root
|
|
590
|
+
.find(j.ClassProperty, {
|
|
591
|
+
key: { name: propName },
|
|
592
|
+
typeAnnotation: {
|
|
593
|
+
typeAnnotation: {
|
|
594
|
+
typeName: { name: componentType },
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
})
|
|
598
|
+
.size() > 0);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return false;
|
|
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;
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
exports.default = default_1;
|
|
31
|
+
const utils_1 = require("../utils");
|
|
32
|
+
const fs = __importStar(require("fs"));
|
|
33
|
+
const index_1 = require("../template-transformer/index");
|
|
34
|
+
function default_1(fileInfo, api) {
|
|
35
|
+
const filePath = fileInfo.path;
|
|
36
|
+
if (filePath.endsWith('.html')) {
|
|
37
|
+
if ((0, utils_1.hasKendoInTemplate)(fileInfo.source)) {
|
|
38
|
+
let updatedContent = fileInfo.source;
|
|
39
|
+
updatedContent = (0, utils_1.htmlEventTransformer)({ ...fileInfo, source: updatedContent }, 'kendo-listbox', 'actionClick', 'action');
|
|
40
|
+
// Only write to file once after all transformations
|
|
41
|
+
fs.writeFileSync(filePath, updatedContent, 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const j = api.jscodeshift;
|
|
46
|
+
const rootSource = j(fileInfo.source);
|
|
47
|
+
(0, index_1.templateTransformer)(rootSource, j, (root) => {
|
|
48
|
+
(0, utils_1.templateEventTransformer)(root, 'kendo-listbox', 'actionClick', 'action');
|
|
49
|
+
});
|
|
50
|
+
(0, utils_1.tsPropertyTransformer)(fileInfo.source, rootSource, j, 'ListBoxComponent', 'actionClick', 'action');
|
|
51
|
+
return rootSource.toSource();
|
|
52
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.default = default_1;
|
|
8
|
+
function default_1(fileInfo, api) {
|
|
9
|
+
const filePath = fileInfo.path;
|
|
10
|
+
if (filePath.endsWith('.html')) {
|
|
11
|
+
// HTML transformations not needed for this migration
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const j = api.jscodeshift;
|
|
15
|
+
const rootSource = j(fileInfo.source);
|
|
16
|
+
tsSelectedIndexTransformer(fileInfo.source, rootSource, j, 'ListBoxComponent');
|
|
17
|
+
return rootSource.toSource();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Custom transformer to convert selectedIndex property access to selectedIndices[0]
|
|
21
|
+
* for ListBoxComponent instances
|
|
22
|
+
*/
|
|
23
|
+
const tsSelectedIndexTransformer = (source, root, j, componentType) => {
|
|
24
|
+
if (source.includes(componentType)) {
|
|
25
|
+
// Find all class properties that are of type ListBoxComponent
|
|
26
|
+
const properties = new Set();
|
|
27
|
+
// Find properties with type annotations
|
|
28
|
+
root.find(j.ClassProperty, {
|
|
29
|
+
typeAnnotation: {
|
|
30
|
+
typeAnnotation: {
|
|
31
|
+
typeName: {
|
|
32
|
+
name: componentType,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}).forEach((path) => {
|
|
37
|
+
if (path.node.key.type === 'Identifier') {
|
|
38
|
+
properties.add(path.node.key.name);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
// Find function parameters of type componentType
|
|
42
|
+
const parameters = new Set();
|
|
43
|
+
root.find(j.FunctionDeclaration).forEach((path) => {
|
|
44
|
+
if (path.node.params) {
|
|
45
|
+
path.node.params.forEach((param) => {
|
|
46
|
+
if (param.type === 'Identifier' &&
|
|
47
|
+
param.typeAnnotation &&
|
|
48
|
+
param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
49
|
+
param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
50
|
+
param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
51
|
+
parameters.add(param.name);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// Also check method declarations in classes
|
|
57
|
+
root.find(j.ClassMethod).forEach((path) => {
|
|
58
|
+
if (path.node.params) {
|
|
59
|
+
path.node.params.forEach((param) => {
|
|
60
|
+
if (param.type === 'Identifier' &&
|
|
61
|
+
param.typeAnnotation &&
|
|
62
|
+
param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
63
|
+
param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
64
|
+
param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
65
|
+
parameters.add(param.name);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
// Also check arrow functions
|
|
71
|
+
root.find(j.ArrowFunctionExpression).forEach((path) => {
|
|
72
|
+
if (path.node.params) {
|
|
73
|
+
path.node.params.forEach((param) => {
|
|
74
|
+
if (param.type === 'Identifier' &&
|
|
75
|
+
param.typeAnnotation &&
|
|
76
|
+
param.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
77
|
+
param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
78
|
+
param.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
79
|
+
parameters.add(param.name);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Find local variable declarations of type componentType
|
|
85
|
+
const localVariables = new Set();
|
|
86
|
+
root.find(j.VariableDeclarator).forEach((path) => {
|
|
87
|
+
if (path.node.id.type === 'Identifier' &&
|
|
88
|
+
path.node.id.typeAnnotation &&
|
|
89
|
+
path.node.id.typeAnnotation.typeAnnotation?.type === 'TSTypeReference' &&
|
|
90
|
+
path.node.id.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' &&
|
|
91
|
+
path.node.id.typeAnnotation.typeAnnotation.typeName.name === componentType) {
|
|
92
|
+
localVariables.add(path.node.id.name);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// Find all member expressions where selectedIndex property is accessed on any ListBoxComponent instance
|
|
96
|
+
root.find(j.MemberExpression, {
|
|
97
|
+
property: {
|
|
98
|
+
type: 'Identifier',
|
|
99
|
+
name: 'selectedIndex',
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
.filter((path) => {
|
|
103
|
+
// Filter to only include accesses on properties that are ListBoxComponent instances
|
|
104
|
+
if (path.node.object.type === 'MemberExpression' && path.node.object.property.type === 'Identifier') {
|
|
105
|
+
// handle properties of this
|
|
106
|
+
if (path.node.object.object.type === 'ThisExpression' &&
|
|
107
|
+
properties.has(path.node.object.property.name)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Handle function parameters and local variables
|
|
112
|
+
if (path.node.object.type === 'Identifier') {
|
|
113
|
+
return parameters.has(path.node.object.name) || localVariables.has(path.node.object.name);
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
})
|
|
117
|
+
.forEach((path) => {
|
|
118
|
+
// Replace selectedIndex with selectedIndices[0]
|
|
119
|
+
const memberExpression = j.memberExpression(j.memberExpression(path.node.object, j.identifier('selectedIndices')), j.numericLiteral(0), true // computed property access (uses brackets)
|
|
120
|
+
);
|
|
121
|
+
// Replace the entire member expression
|
|
122
|
+
j(path).replaceWith(memberExpression);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.default = default_1;
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
function default_1(fileInfo, api) {
|
|
10
|
+
const j = api.jscodeshift;
|
|
11
|
+
const rootSource = j(fileInfo.source);
|
|
12
|
+
(0, utils_1.tsInterfaceTransformer)(fileInfo, rootSource, j, '@progress/kendo-angular-listbox', 'Toolbar', 'ListBoxToolbarConfig');
|
|
13
|
+
return rootSource.toSource();
|
|
14
|
+
}
|
|
@@ -10,7 +10,7 @@ export const packageMetadata = {
|
|
|
10
10
|
productName: 'Kendo UI for Angular',
|
|
11
11
|
productCode: 'KENDOUIANGULAR',
|
|
12
12
|
productCodes: ['KENDOUIANGULAR'],
|
|
13
|
-
publishDate:
|
|
14
|
-
version: '21.0.0-develop.
|
|
13
|
+
publishDate: 1762263863,
|
|
14
|
+
version: '21.0.0-develop.18',
|
|
15
15
|
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
|
|
16
16
|
};
|
|
@@ -25,8 +25,8 @@ const packageMetadata = {
|
|
|
25
25
|
productName: 'Kendo UI for Angular',
|
|
26
26
|
productCode: 'KENDOUIANGULAR',
|
|
27
27
|
productCodes: ['KENDOUIANGULAR'],
|
|
28
|
-
publishDate:
|
|
29
|
-
version: '21.0.0-develop.
|
|
28
|
+
publishDate: 1762263863,
|
|
29
|
+
version: '21.0.0-develop.18',
|
|
30
30
|
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
|
|
31
31
|
};
|
|
32
32
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@progress/kendo-angular-listbox",
|
|
3
|
-
"version": "21.0.0-develop.
|
|
3
|
+
"version": "21.0.0-develop.18",
|
|
4
4
|
"description": "Kendo UI for Angular ListBox",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "Progress",
|
|
@@ -16,10 +16,35 @@
|
|
|
16
16
|
],
|
|
17
17
|
"@progress": {
|
|
18
18
|
"friendlyName": "ListBox",
|
|
19
|
+
"migrations": {
|
|
20
|
+
"options": {
|
|
21
|
+
"parser": "tsx",
|
|
22
|
+
"pattern": "*.{ts,html}"
|
|
23
|
+
},
|
|
24
|
+
"codemods": {
|
|
25
|
+
"19": [
|
|
26
|
+
{
|
|
27
|
+
"description": "Migrate selectedIndex to selectedIndices for ListBox component.",
|
|
28
|
+
"file": "codemods/v21/listbox-selectedindex.js",
|
|
29
|
+
"prompt": "true"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"description": "Migrate actionClick to action for ListBox component.",
|
|
33
|
+
"file": "codemods/v21/listbox-actionclick.js",
|
|
34
|
+
"prompt": "true"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"description": "Migrate Toolbar interface name to ListBoxToolbarConfig.",
|
|
38
|
+
"file": "codemods/v21/listbox-toolbar.js",
|
|
39
|
+
"prompt": "true"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
19
44
|
"package": {
|
|
20
45
|
"productName": "Kendo UI for Angular",
|
|
21
46
|
"productCode": "KENDOUIANGULAR",
|
|
22
|
-
"publishDate":
|
|
47
|
+
"publishDate": 1762263863,
|
|
23
48
|
"licensingDocsUrl": "https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning"
|
|
24
49
|
}
|
|
25
50
|
},
|
|
@@ -29,15 +54,16 @@
|
|
|
29
54
|
"@angular/core": "18 - 20",
|
|
30
55
|
"@angular/platform-browser": "18 - 20",
|
|
31
56
|
"@progress/kendo-licensing": "^1.7.0",
|
|
32
|
-
"@progress/kendo-angular-buttons": "21.0.0-develop.
|
|
33
|
-
"@progress/kendo-angular-common": "21.0.0-develop.
|
|
34
|
-
"@progress/kendo-angular-popup": "21.0.0-develop.
|
|
57
|
+
"@progress/kendo-angular-buttons": "21.0.0-develop.18",
|
|
58
|
+
"@progress/kendo-angular-common": "21.0.0-develop.18",
|
|
59
|
+
"@progress/kendo-angular-popup": "21.0.0-develop.18",
|
|
35
60
|
"rxjs": "^6.5.3 || ^7.0.0"
|
|
36
61
|
},
|
|
37
62
|
"dependencies": {
|
|
38
63
|
"tslib": "^2.3.1",
|
|
39
|
-
"@progress/kendo-angular-schematics": "21.0.0-develop.
|
|
40
|
-
"@progress/kendo-common": "^1.0.1"
|
|
64
|
+
"@progress/kendo-angular-schematics": "21.0.0-develop.18",
|
|
65
|
+
"@progress/kendo-common": "^1.0.1",
|
|
66
|
+
"node-html-parser": "^7.0.1"
|
|
41
67
|
},
|
|
42
68
|
"schematics": "./schematics/collection.json",
|
|
43
69
|
"module": "fesm2022/progress-kendo-angular-listbox.mjs",
|
|
@@ -7,11 +7,11 @@ function default_1(options) {
|
|
|
7
7
|
// Additional dependencies to install.
|
|
8
8
|
// See https://github.com/telerik/kendo-schematics/issues/28
|
|
9
9
|
peerDependencies: {
|
|
10
|
-
'@progress/kendo-angular-buttons': '21.0.0-develop.
|
|
11
|
-
'@progress/kendo-angular-common': '21.0.0-develop.
|
|
12
|
-
'@progress/kendo-angular-l10n': '21.0.0-develop.
|
|
10
|
+
'@progress/kendo-angular-buttons': '21.0.0-develop.18',
|
|
11
|
+
'@progress/kendo-angular-common': '21.0.0-develop.18',
|
|
12
|
+
'@progress/kendo-angular-l10n': '21.0.0-develop.18',
|
|
13
13
|
// Peer of kendo-angular-buttons
|
|
14
|
-
'@progress/kendo-angular-popup': '21.0.0-develop.
|
|
14
|
+
'@progress/kendo-angular-popup': '21.0.0-develop.18'
|
|
15
15
|
} });
|
|
16
16
|
return (0, schematics_1.externalSchematic)('@progress/kendo-angular-schematics', 'ng-add', finalOptions);
|
|
17
17
|
}
|