@teambit/typescript 0.0.1100 → 0.0.1102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/{preview-1688786141872.js → preview-1689061040556.js} +2 -2
- package/dist/sourceFileTransformers/class.d.ts +2 -0
- package/dist/sourceFileTransformers/class.js +38 -0
- package/dist/sourceFileTransformers/class.js.map +1 -0
- package/dist/sourceFileTransformers/empty-line-encoder.d.ts +14 -0
- package/dist/sourceFileTransformers/empty-line-encoder.js +68 -0
- package/dist/sourceFileTransformers/empty-line-encoder.js.map +1 -0
- package/dist/sourceFileTransformers/export.d.ts +2 -0
- package/dist/sourceFileTransformers/export.js +61 -0
- package/dist/sourceFileTransformers/export.js.map +1 -0
- package/dist/sourceFileTransformers/function.d.ts +2 -0
- package/dist/sourceFileTransformers/function.js +110 -0
- package/dist/sourceFileTransformers/function.js.map +1 -0
- package/dist/sourceFileTransformers/identifier.d.ts +2 -0
- package/dist/sourceFileTransformers/identifier.js +38 -0
- package/dist/sourceFileTransformers/identifier.js.map +1 -0
- package/dist/sourceFileTransformers/import.d.ts +2 -0
- package/dist/sourceFileTransformers/import.js +74 -0
- package/dist/sourceFileTransformers/import.js.map +1 -0
- package/dist/sourceFileTransformers/index.d.ts +11 -0
- package/dist/sourceFileTransformers/index.js +124 -0
- package/dist/sourceFileTransformers/index.js.map +1 -0
- package/dist/sourceFileTransformers/interface.d.ts +2 -0
- package/dist/sourceFileTransformers/interface.js +38 -0
- package/dist/sourceFileTransformers/interface.js.map +1 -0
- package/dist/sourceFileTransformers/transform.d.ts +12 -0
- package/dist/sourceFileTransformers/transform.js +113 -0
- package/dist/sourceFileTransformers/transform.js.map +1 -0
- package/dist/sourceFileTransformers/typeAlias.d.ts +2 -0
- package/dist/sourceFileTransformers/typeAlias.js +38 -0
- package/dist/sourceFileTransformers/typeAlias.js.map +1 -0
- package/dist/sourceFileTransformers/variable.d.ts +2 -0
- package/dist/sourceFileTransformers/variable.js +38 -0
- package/dist/sourceFileTransformers/variable.js.map +1 -0
- package/dist/transform-source-file.spec.d.ts +1 -0
- package/dist/transform-source-file.spec.js +109 -0
- package/dist/transform-source-file.spec.js.map +1 -0
- package/package-tar/teambit-typescript-0.0.1102.tgz +0 -0
- package/package.json +19 -19
- package/sourceFileTransformers/class.ts +29 -0
- package/sourceFileTransformers/empty-line-encoder.ts +56 -0
- package/sourceFileTransformers/export.ts +65 -0
- package/sourceFileTransformers/function.ts +164 -0
- package/sourceFileTransformers/identifier.ts +24 -0
- package/sourceFileTransformers/import.ts +103 -0
- package/sourceFileTransformers/index.ts +13 -0
- package/sourceFileTransformers/interface.ts +29 -0
- package/sourceFileTransformers/transform.ts +100 -0
- package/sourceFileTransformers/typeAlias.ts +28 -0
- package/sourceFileTransformers/variable.ts +28 -0
- package/package-tar/teambit-typescript-0.0.1100.tgz +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
export function classNamesTransformer(nameMapping: Record<string, string>): ts.TransformerFactory<ts.SourceFile> {
|
|
4
|
+
return (context) => {
|
|
5
|
+
const { factory } = context;
|
|
6
|
+
const visit: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isClassDeclaration(node) && node.name) {
|
|
8
|
+
const oldName = node.name.text;
|
|
9
|
+
const newName = Object.keys(nameMapping).find((key) => oldName.startsWith(key) || oldName.endsWith(key));
|
|
10
|
+
if (newName) {
|
|
11
|
+
const replacedName = oldName.startsWith(newName)
|
|
12
|
+
? oldName.replace(newName, nameMapping[newName])
|
|
13
|
+
: oldName.replace(new RegExp(`${newName}$`), nameMapping[newName]);
|
|
14
|
+
return factory.updateClassDeclaration(
|
|
15
|
+
node,
|
|
16
|
+
node.decorators,
|
|
17
|
+
node.modifiers,
|
|
18
|
+
factory.createIdentifier(replacedName),
|
|
19
|
+
node.typeParameters,
|
|
20
|
+
node.heritageClauses,
|
|
21
|
+
node.members
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return ts.visitEachChild(node, (child) => visit(child), context);
|
|
26
|
+
};
|
|
27
|
+
return (node) => ts.visitNode(node, visit);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
export class EmptyLineEncoder {
|
|
4
|
+
static readonly defaultEmptyLineMarker: string = '!--empty-line--!';
|
|
5
|
+
static readonly defaultNewLine: string = '\r\n';
|
|
6
|
+
constructor(emptyLineMarker?: string, newLine?: string) {
|
|
7
|
+
this.emptyLineMarker = emptyLineMarker || EmptyLineEncoder.defaultEmptyLineMarker;
|
|
8
|
+
this.newLine = newLine || EmptyLineEncoder.defaultNewLine;
|
|
9
|
+
}
|
|
10
|
+
emptyLineMarker: string;
|
|
11
|
+
newLine: string;
|
|
12
|
+
|
|
13
|
+
encode(text: string) {
|
|
14
|
+
return encodeEmptyLines(text, this.emptyLineMarker, this.newLine);
|
|
15
|
+
}
|
|
16
|
+
decode(text: string) {
|
|
17
|
+
return decodeEmptyLines(text, this.emptyLineMarker, this.newLine);
|
|
18
|
+
}
|
|
19
|
+
addLeadingEmptyLineMarker<T extends ts.Node>(node: T) {
|
|
20
|
+
return addLeadingEmptyLineMarker(node, this.emptyLineMarker);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function encodeEmptyLines(text: string, emptyLineMarker?: string, newLine?: string) {
|
|
25
|
+
const marker = toComment(emptyLineMarker || EmptyLineEncoder.defaultEmptyLineMarker);
|
|
26
|
+
|
|
27
|
+
const lines = text.split(/\r?\n/);
|
|
28
|
+
|
|
29
|
+
const commentedLines = lines.map((line) => (line.trim() === '' ? marker : line));
|
|
30
|
+
|
|
31
|
+
return commentedLines.join(newLine || EmptyLineEncoder.defaultNewLine);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function decodeEmptyLines(text: string, emptyLineMarker?: string, newLine?: string) {
|
|
35
|
+
const marker = toComment(emptyLineMarker || EmptyLineEncoder.defaultEmptyLineMarker);
|
|
36
|
+
|
|
37
|
+
const lines = text.split(/\r?\n/);
|
|
38
|
+
|
|
39
|
+
const uncommentedLines = lines.map((line) => (line === marker ? '' : line));
|
|
40
|
+
|
|
41
|
+
return uncommentedLines.join(newLine || EmptyLineEncoder.defaultNewLine);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function addLeadingEmptyLineMarker<T extends ts.Node>(node: T, emptyLineMarker?: string) {
|
|
45
|
+
return ts.addSyntheticLeadingComment(
|
|
46
|
+
node,
|
|
47
|
+
ts.SyntaxKind.MultiLineCommentTrivia,
|
|
48
|
+
emptyLineMarker || EmptyLineEncoder.defaultEmptyLineMarker,
|
|
49
|
+
// hasTrailingNewLine
|
|
50
|
+
true
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function toComment(marker: string) {
|
|
55
|
+
return `/*${marker}*/`;
|
|
56
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { SourceFileTransformer } from '.';
|
|
3
|
+
|
|
4
|
+
export const exportTransformer: SourceFileTransformer = (mapping: Record<string, string>) => {
|
|
5
|
+
return (context) => {
|
|
6
|
+
const visit: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isExportDeclaration(node)) {
|
|
8
|
+
let moduleSpecifier = node.moduleSpecifier?.getText().slice(1, -1);
|
|
9
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
10
|
+
if (moduleSpecifier && moduleSpecifier.includes(oldName)) {
|
|
11
|
+
moduleSpecifier = moduleSpecifier.replace(oldName, newName);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
|
|
16
|
+
const transformedElements = node.exportClause.elements.map((element) => {
|
|
17
|
+
let newElementName = element.name.text;
|
|
18
|
+
|
|
19
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
20
|
+
if (newElementName.startsWith(oldName) || newElementName.endsWith(oldName)) {
|
|
21
|
+
newElementName = newElementName.replace(oldName, newName);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return ts.factory.updateExportSpecifier(
|
|
26
|
+
element,
|
|
27
|
+
false,
|
|
28
|
+
element.propertyName,
|
|
29
|
+
ts.factory.createIdentifier(newElementName)
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const updatedExportClause = ts.factory.updateNamedExports(node.exportClause, transformedElements);
|
|
34
|
+
|
|
35
|
+
return ts.factory.updateExportDeclaration(
|
|
36
|
+
node,
|
|
37
|
+
node.decorators,
|
|
38
|
+
node.modifiers,
|
|
39
|
+
node.isTypeOnly,
|
|
40
|
+
updatedExportClause,
|
|
41
|
+
node.moduleSpecifier ? ts.factory.createStringLiteral(moduleSpecifier || '') : undefined,
|
|
42
|
+
undefined
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (ts.isExportAssignment(node)) {
|
|
48
|
+
let expression = node.expression;
|
|
49
|
+
|
|
50
|
+
if (ts.isIdentifier(expression)) {
|
|
51
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
52
|
+
if (expression.getText().startsWith(oldName) || expression.getText().endsWith(oldName)) {
|
|
53
|
+
expression = ts.factory.createIdentifier(expression.getText().replace(oldName, newName));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return ts.factory.updateExportAssignment(node, node.decorators, node.modifiers, expression);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return ts.visitEachChild(node, visit, context);
|
|
62
|
+
};
|
|
63
|
+
return (node) => ts.visitNode(node, visit);
|
|
64
|
+
};
|
|
65
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { SourceFileTransformer } from '.';
|
|
3
|
+
|
|
4
|
+
export const functionNamesTransformer: SourceFileTransformer = (mapping: Record<string, string>) => {
|
|
5
|
+
return (context) => {
|
|
6
|
+
const updateTypeReference: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
8
|
+
const typeName = node.typeName.getText();
|
|
9
|
+
const newTypeName = mapping[typeName];
|
|
10
|
+
if (newTypeName) {
|
|
11
|
+
return ts.factory.updateTypeReferenceNode(node, ts.factory.createIdentifier(newTypeName), node.typeArguments);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return ts.visitEachChild(node, updateTypeReference, context);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const visit: ts.Visitor = (node) => {
|
|
18
|
+
if (ts.isFunctionDeclaration(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
19
|
+
const functionName = node.name?.getText() ?? '';
|
|
20
|
+
const newName = Object.entries(mapping).find(([key]) => functionName.includes(key))?.[1] ?? functionName;
|
|
21
|
+
const parameters = node.parameters.map((param) => {
|
|
22
|
+
const newParamType = param.type ? ts.visitNode(param.type, updateTypeReference) : param.type;
|
|
23
|
+
if (ts.isIdentifier(param.name)) {
|
|
24
|
+
const oldName = param.name.getText();
|
|
25
|
+
const newParamName = Object.keys(mapping).find((key) => oldName.includes(key));
|
|
26
|
+
if (newParamName) {
|
|
27
|
+
return ts.factory.updateParameterDeclaration(
|
|
28
|
+
param,
|
|
29
|
+
param.decorators,
|
|
30
|
+
param.modifiers,
|
|
31
|
+
param.dotDotDotToken,
|
|
32
|
+
ts.factory.createIdentifier(newParamName),
|
|
33
|
+
param.questionToken,
|
|
34
|
+
newParamType,
|
|
35
|
+
param.initializer
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
} else if (ts.isObjectBindingPattern(param.name)) {
|
|
39
|
+
const elements = param.name.elements.map((element) => {
|
|
40
|
+
const newElementName = mapping[element.name.getText()];
|
|
41
|
+
if (newElementName) {
|
|
42
|
+
return ts.factory.updateBindingElement(
|
|
43
|
+
element,
|
|
44
|
+
element.dotDotDotToken,
|
|
45
|
+
element.propertyName,
|
|
46
|
+
ts.factory.createIdentifier(newElementName),
|
|
47
|
+
element.initializer
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return element;
|
|
51
|
+
});
|
|
52
|
+
const newParamName = ts.factory.createObjectBindingPattern(elements);
|
|
53
|
+
return ts.factory.updateParameterDeclaration(
|
|
54
|
+
param,
|
|
55
|
+
param.decorators,
|
|
56
|
+
param.modifiers,
|
|
57
|
+
param.dotDotDotToken,
|
|
58
|
+
newParamName,
|
|
59
|
+
param.questionToken,
|
|
60
|
+
newParamType,
|
|
61
|
+
param.initializer
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return param;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (ts.isFunctionDeclaration(node)) {
|
|
68
|
+
const updatedBody = node.body && ts.isBlock(node.body) ? updateReturnStatement(node.body) : node.body;
|
|
69
|
+
return ts.factory.updateFunctionDeclaration(
|
|
70
|
+
node,
|
|
71
|
+
node.decorators,
|
|
72
|
+
node.modifiers,
|
|
73
|
+
node.asteriskToken,
|
|
74
|
+
newName ? ts.factory.createIdentifier(newName) : node.name,
|
|
75
|
+
node.typeParameters,
|
|
76
|
+
parameters,
|
|
77
|
+
node.type,
|
|
78
|
+
updatedBody
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (ts.isArrowFunction(node)) {
|
|
82
|
+
const updatedBody = node.body && ts.isBlock(node.body) ? updateReturnStatement(node.body) : node.body;
|
|
83
|
+
return ts.factory.updateArrowFunction(
|
|
84
|
+
node,
|
|
85
|
+
node.modifiers,
|
|
86
|
+
node.typeParameters,
|
|
87
|
+
parameters,
|
|
88
|
+
node.type,
|
|
89
|
+
node.equalsGreaterThanToken,
|
|
90
|
+
updatedBody
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
if (ts.isFunctionExpression(node)) {
|
|
94
|
+
const updatedBody = node.body && ts.isBlock(node.body) ? updateReturnStatement(node.body) : node.body;
|
|
95
|
+
return ts.factory.updateFunctionExpression(
|
|
96
|
+
node,
|
|
97
|
+
node.modifiers,
|
|
98
|
+
node.asteriskToken,
|
|
99
|
+
newName ? ts.factory.createIdentifier(newName) : node.name,
|
|
100
|
+
node.typeParameters,
|
|
101
|
+
parameters,
|
|
102
|
+
node.type,
|
|
103
|
+
updatedBody
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return ts.visitEachChild(node, visit, context);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
function updateReturnStatement(body: ts.ConciseBody): ts.Block {
|
|
111
|
+
if (ts.isBlock(body)) {
|
|
112
|
+
const updatedStatements: ts.Statement[] = [];
|
|
113
|
+
for (const statement of body.statements) {
|
|
114
|
+
if (ts.isReturnStatement(statement) && statement.expression && ts.isJsxElement(statement.expression)) {
|
|
115
|
+
const jsxElement = statement.expression;
|
|
116
|
+
const openingElement = jsxElement.openingElement;
|
|
117
|
+
const tagName = openingElement.tagName.getText();
|
|
118
|
+
const newTagName = mapping[tagName];
|
|
119
|
+
if (newTagName) {
|
|
120
|
+
const updatedTagName = ts.factory.createIdentifier(newTagName);
|
|
121
|
+
const updatedOpeningElement = ts.factory.updateJsxOpeningElement(
|
|
122
|
+
openingElement,
|
|
123
|
+
updatedTagName,
|
|
124
|
+
openingElement.typeArguments,
|
|
125
|
+
openingElement.attributes
|
|
126
|
+
);
|
|
127
|
+
const updatedClosingElement = jsxElement.closingElement
|
|
128
|
+
? ts.factory.updateJsxClosingElement(jsxElement.closingElement, updatedTagName)
|
|
129
|
+
: ts.factory.createJsxClosingElement(updatedTagName);
|
|
130
|
+
const updatedJsxElement = ts.factory.createJsxElement(
|
|
131
|
+
updatedOpeningElement,
|
|
132
|
+
jsxElement.children,
|
|
133
|
+
updatedClosingElement
|
|
134
|
+
);
|
|
135
|
+
const updatedStatement = ts.factory.createReturnStatement(updatedJsxElement);
|
|
136
|
+
updatedStatements.push(updatedStatement);
|
|
137
|
+
} else {
|
|
138
|
+
updatedStatements.push(statement);
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
updatedStatements.push(statement);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return ts.factory.updateBlock(body, updatedStatements);
|
|
145
|
+
}
|
|
146
|
+
if (
|
|
147
|
+
ts.isExpressionStatement(body) &&
|
|
148
|
+
ts.isReturnStatement(body.expression) &&
|
|
149
|
+
body.expression.expression &&
|
|
150
|
+
ts.isIdentifier(body.expression.expression)
|
|
151
|
+
) {
|
|
152
|
+
const oldName = body.expression.expression.text;
|
|
153
|
+
const newName = mapping[oldName];
|
|
154
|
+
if (newName) {
|
|
155
|
+
const updatedExpression = ts.factory.createIdentifier(newName);
|
|
156
|
+
const updatedReturnStatement = ts.factory.createReturnStatement(updatedExpression);
|
|
157
|
+
return ts.factory.createBlock([updatedReturnStatement], true);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return ts.factory.createBlock([], true);
|
|
161
|
+
}
|
|
162
|
+
return (node) => ts.visitNode(node, visit);
|
|
163
|
+
};
|
|
164
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { SourceFileTransformer } from '.';
|
|
3
|
+
|
|
4
|
+
export const identifierTransformer: SourceFileTransformer = (mapping: Record<string, string>) => {
|
|
5
|
+
return (context) => {
|
|
6
|
+
const visit: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isIdentifier(node)) {
|
|
8
|
+
const identifierName = node.text;
|
|
9
|
+
let newIdentifierName = mapping[identifierName] || identifierName;
|
|
10
|
+
|
|
11
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
12
|
+
if (identifierName.startsWith(oldName) || identifierName.endsWith(oldName)) {
|
|
13
|
+
newIdentifierName = identifierName.replace(oldName, newName);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return ts.factory.createIdentifier(newIdentifierName);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return ts.visitEachChild(node, visit, context);
|
|
21
|
+
};
|
|
22
|
+
return (node) => ts.visitNode(node, visit);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { SourceFileTransformer } from '.';
|
|
3
|
+
|
|
4
|
+
export const importTransformer: SourceFileTransformer = (mapping: Record<string, string>) => {
|
|
5
|
+
return (context) => {
|
|
6
|
+
const visit: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isImportDeclaration(node)) {
|
|
8
|
+
let moduleSpecifier = node.moduleSpecifier.getText().slice(1, -1);
|
|
9
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
10
|
+
if (moduleSpecifier.includes(oldName)) {
|
|
11
|
+
moduleSpecifier = moduleSpecifier.replace(oldName, newName);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {
|
|
16
|
+
const transformedBindings = node.importClause.namedBindings.elements.map((element) => {
|
|
17
|
+
let newElementName = element.name.text;
|
|
18
|
+
|
|
19
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
20
|
+
if (newElementName.startsWith(oldName) || newElementName.endsWith(oldName)) {
|
|
21
|
+
newElementName = newElementName.replace(oldName, newName);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return ts.factory.updateImportSpecifier(
|
|
26
|
+
element,
|
|
27
|
+
false,
|
|
28
|
+
element.propertyName ? ts.factory.createIdentifier(newElementName) : undefined,
|
|
29
|
+
ts.factory.createIdentifier(newElementName)
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const updatedImportClause = ts.factory.updateImportClause(
|
|
34
|
+
node.importClause,
|
|
35
|
+
node.importClause.isTypeOnly,
|
|
36
|
+
node.importClause.name,
|
|
37
|
+
ts.factory.createNamedImports(transformedBindings)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return ts.factory.updateImportDeclaration(
|
|
41
|
+
node,
|
|
42
|
+
node.decorators,
|
|
43
|
+
node.modifiers,
|
|
44
|
+
updatedImportClause,
|
|
45
|
+
ts.factory.createStringLiteral(moduleSpecifier),
|
|
46
|
+
undefined
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return ts.factory.updateImportDeclaration(
|
|
51
|
+
node,
|
|
52
|
+
node.decorators,
|
|
53
|
+
node.modifiers,
|
|
54
|
+
node.importClause,
|
|
55
|
+
ts.factory.createStringLiteral(moduleSpecifier),
|
|
56
|
+
undefined
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (ts.isImportEqualsDeclaration(node)) {
|
|
60
|
+
let moduleSpecifier = node.moduleReference.getText().slice(1, -1);
|
|
61
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
62
|
+
if (moduleSpecifier.includes(oldName)) {
|
|
63
|
+
moduleSpecifier = moduleSpecifier.replace(oldName, newName);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const updatedImportEqualsDeclaration = ts.factory.updateImportEqualsDeclaration(
|
|
68
|
+
node,
|
|
69
|
+
node.decorators,
|
|
70
|
+
node.modifiers,
|
|
71
|
+
node.isTypeOnly,
|
|
72
|
+
node.name,
|
|
73
|
+
ts.factory.createExternalModuleReference(ts.factory.createStringLiteral(moduleSpecifier))
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return updatedImportEqualsDeclaration;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'require') {
|
|
80
|
+
const [firstArg] = node.arguments;
|
|
81
|
+
|
|
82
|
+
if (ts.isStringLiteral(firstArg)) {
|
|
83
|
+
let moduleSpecifier = firstArg.text;
|
|
84
|
+
|
|
85
|
+
for (const [oldName, newName] of Object.entries(mapping)) {
|
|
86
|
+
if (moduleSpecifier.includes(oldName)) {
|
|
87
|
+
moduleSpecifier = moduleSpecifier.replace(oldName, newName);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const updatedArg = ts.factory.createStringLiteral(moduleSpecifier);
|
|
92
|
+
return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [
|
|
93
|
+
updatedArg,
|
|
94
|
+
...node.arguments.slice(1),
|
|
95
|
+
]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return ts.visitEachChild(node, visit, context);
|
|
100
|
+
};
|
|
101
|
+
return (node) => ts.visitNode(node, visit);
|
|
102
|
+
};
|
|
103
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
export type SourceFileTransformer = (mapping: Record<string, string>) => ts.TransformerFactory<ts.SourceFile>;
|
|
4
|
+
|
|
5
|
+
export { classNamesTransformer } from './class';
|
|
6
|
+
export { interfaceNamesTransformer } from './interface';
|
|
7
|
+
export { variableNamesTransformer } from './variable';
|
|
8
|
+
export { functionNamesTransformer } from './function';
|
|
9
|
+
export { typeAliasNamesTransformer } from './typeAlias';
|
|
10
|
+
export { importTransformer } from './import';
|
|
11
|
+
export { identifierTransformer } from './identifier';
|
|
12
|
+
export { exportTransformer } from './export';
|
|
13
|
+
export { transformSourceFile } from './transform';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
export function interfaceNamesTransformer(nameMapping: Record<string, string>): ts.TransformerFactory<ts.SourceFile> {
|
|
4
|
+
return (context) => {
|
|
5
|
+
const { factory } = context;
|
|
6
|
+
const visit: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isInterfaceDeclaration(node)) {
|
|
8
|
+
const oldName = node.name.text;
|
|
9
|
+
const newName = Object.keys(nameMapping).find((key) => oldName.startsWith(key) || oldName.endsWith(key));
|
|
10
|
+
if (newName) {
|
|
11
|
+
const replacedName = oldName.startsWith(newName)
|
|
12
|
+
? oldName.replace(newName, nameMapping[newName])
|
|
13
|
+
: oldName.replace(new RegExp(`${newName}$`), nameMapping[newName]);
|
|
14
|
+
return factory.updateInterfaceDeclaration(
|
|
15
|
+
node,
|
|
16
|
+
node.decorators,
|
|
17
|
+
node.modifiers,
|
|
18
|
+
factory.createIdentifier(replacedName),
|
|
19
|
+
node.typeParameters,
|
|
20
|
+
node.heritageClauses,
|
|
21
|
+
node.members
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return ts.visitEachChild(node, (child) => visit(child), context);
|
|
26
|
+
};
|
|
27
|
+
return (node) => ts.visitNode(node, visit);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Formatter } from '@teambit/formatter';
|
|
2
|
+
import ts from 'typescript';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { EmptyLineEncoder } from './empty-line-encoder';
|
|
5
|
+
/**
|
|
6
|
+
* Transforms a TypeScript source file using the provided transformer.
|
|
7
|
+
*
|
|
8
|
+
* @param sourceFilePath Path to the TypeScript source file.
|
|
9
|
+
* @param sourceFileContent The content of the source file.
|
|
10
|
+
* @param transformers The transformers to be applied on the source file.
|
|
11
|
+
* @param formatter (Optional) An optional formatter to format the transformed code. If no formatter is provided, the function returns the transformed source file as a string without any formatting.
|
|
12
|
+
* @returns A promise that resolves to the transformed source file as a string.
|
|
13
|
+
*/
|
|
14
|
+
export async function transformSourceFile(
|
|
15
|
+
sourceFilePath: string,
|
|
16
|
+
sourceFileContent: string,
|
|
17
|
+
transformers: ts.TransformerFactory<ts.SourceFile>[],
|
|
18
|
+
formatter?: Formatter,
|
|
19
|
+
updates?: Record<string, string>
|
|
20
|
+
): Promise<string> {
|
|
21
|
+
const ext = path.extname(sourceFilePath);
|
|
22
|
+
const compatibleExts = ['.ts', '.tsx', '.js', '.jsx'];
|
|
23
|
+
if (!compatibleExts.includes(ext)) {
|
|
24
|
+
if (!updates) return sourceFileContent;
|
|
25
|
+
let transformed = sourceFileContent;
|
|
26
|
+
Object.entries(updates).forEach(([oldStr, newStr]) => {
|
|
27
|
+
const oldStringRegex = new RegExp(oldStr, 'g');
|
|
28
|
+
transformed = transformed.replace(oldStringRegex, newStr);
|
|
29
|
+
});
|
|
30
|
+
return transformed;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const encoder = new EmptyLineEncoder();
|
|
34
|
+
sourceFileContent = encoder.encode(sourceFileContent);
|
|
35
|
+
|
|
36
|
+
const sourceFile = ts.createSourceFile(
|
|
37
|
+
sourceFilePath,
|
|
38
|
+
sourceFileContent,
|
|
39
|
+
ts.ScriptTarget.Latest,
|
|
40
|
+
true,
|
|
41
|
+
ts.ScriptKind.TSX
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const transformedResult: ts.TransformationResult<ts.SourceFile> = ts.transform<ts.SourceFile>(
|
|
45
|
+
sourceFile,
|
|
46
|
+
transformers
|
|
47
|
+
);
|
|
48
|
+
const transformedSourceFile: ts.SourceFile = transformedResult.transformed[0] as ts.SourceFile;
|
|
49
|
+
|
|
50
|
+
// const _identifierTransformer = identifierTransformer(updates || {});
|
|
51
|
+
|
|
52
|
+
// const transformedResultWithIdentifiers: ts.TransformationResult<ts.SourceFile> =
|
|
53
|
+
// ts.transform<ts.SourceFile>(transformedSourceFile, []);
|
|
54
|
+
// const transformedSourceFileWithIdentifiers: ts.SourceFile
|
|
55
|
+
// = transformedResultWithIdentifiers.transformed[0] as ts.SourceFile;
|
|
56
|
+
|
|
57
|
+
const printer: ts.Printer = ts.createPrinter({
|
|
58
|
+
removeComments: false,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
let transformedSourceFileStr = printer.printFile(transformedSourceFile);
|
|
62
|
+
transformedSourceFileStr = encoder.decode(transformedSourceFileStr);
|
|
63
|
+
// Remove trailing empty line markers
|
|
64
|
+
const emptyLineComment = `\\s*\\/\\*${encoder.emptyLineMarker}\\*\\/\\s*$`;
|
|
65
|
+
const regex = new RegExp(emptyLineComment, 'g');
|
|
66
|
+
transformedSourceFileStr = transformedSourceFileStr.replace(regex, '');
|
|
67
|
+
|
|
68
|
+
const formattedSourceFileStr = await formatter?.formatSnippet(transformedSourceFileStr);
|
|
69
|
+
return formattedSourceFileStr || transformedSourceFileStr;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// function createMarkingTransformer<T extends ts.Node>(innerTransformer: ts.TransformerFactory<T>)
|
|
73
|
+
// : ts.TransformerFactory<T> {
|
|
74
|
+
// return context => {
|
|
75
|
+
// const innerTransform = innerTransformer(context);
|
|
76
|
+
|
|
77
|
+
// return node => {
|
|
78
|
+
// const result = innerTransform(node);
|
|
79
|
+
|
|
80
|
+
// // Add a custom property to the node to mark it as transformed
|
|
81
|
+
// // Note: this relies on TypeScript's internal behavior and may not be stable across versions
|
|
82
|
+
// (result as any).__transformed = true;
|
|
83
|
+
|
|
84
|
+
// return result;
|
|
85
|
+
// };
|
|
86
|
+
// };
|
|
87
|
+
// }
|
|
88
|
+
|
|
89
|
+
// const defaultTransformer: ts.TransformerFactory<ts.SourceFile> = () => {
|
|
90
|
+
// const visit: ts.Visitor = node => {
|
|
91
|
+
// // If the node has been marked as transformed by a specific transformer, don't transform it
|
|
92
|
+
// if ((node as any).__transformed) {
|
|
93
|
+
// return node;
|
|
94
|
+
// }
|
|
95
|
+
|
|
96
|
+
// // Your transformation logic goes here...
|
|
97
|
+
// };
|
|
98
|
+
|
|
99
|
+
// return node => ts.visitNode(node, visit);
|
|
100
|
+
// };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
export function typeAliasNamesTransformer(nameMapping: Record<string, string>): ts.TransformerFactory<ts.SourceFile> {
|
|
4
|
+
return (context) => {
|
|
5
|
+
const { factory } = context;
|
|
6
|
+
const visit: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isTypeAliasDeclaration(node)) {
|
|
8
|
+
const oldName = node.name.text;
|
|
9
|
+
const newName = Object.keys(nameMapping).find((key) => oldName.startsWith(key) || oldName.endsWith(key));
|
|
10
|
+
if (newName) {
|
|
11
|
+
const replacedName = oldName.startsWith(newName)
|
|
12
|
+
? oldName.replace(newName, nameMapping[newName])
|
|
13
|
+
: oldName.replace(new RegExp(`${newName}$`), nameMapping[newName]);
|
|
14
|
+
return factory.updateTypeAliasDeclaration(
|
|
15
|
+
node,
|
|
16
|
+
node.decorators,
|
|
17
|
+
node.modifiers,
|
|
18
|
+
factory.createIdentifier(replacedName),
|
|
19
|
+
node.typeParameters,
|
|
20
|
+
node.type
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return ts.visitEachChild(node, (child) => visit(child), context);
|
|
25
|
+
};
|
|
26
|
+
return (node) => ts.visitNode(node, visit);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
export function variableNamesTransformer(nameMapping: Record<string, string>): ts.TransformerFactory<ts.SourceFile> {
|
|
4
|
+
return (context) => {
|
|
5
|
+
const { factory } = context;
|
|
6
|
+
const visit: ts.Visitor = (node) => {
|
|
7
|
+
if (ts.isVariableDeclaration(node) && node.name.kind === ts.SyntaxKind.Identifier) {
|
|
8
|
+
const oldName = node.name.text;
|
|
9
|
+
const newName = Object.keys(nameMapping).find((key) => oldName.startsWith(key) || oldName.endsWith(key));
|
|
10
|
+
if (newName) {
|
|
11
|
+
const replacedName = oldName.startsWith(newName)
|
|
12
|
+
? oldName.replace(newName, nameMapping[newName])
|
|
13
|
+
: oldName.replace(new RegExp(`${newName}$`), nameMapping[newName]);
|
|
14
|
+
|
|
15
|
+
return factory.updateVariableDeclaration(
|
|
16
|
+
node,
|
|
17
|
+
factory.createIdentifier(replacedName),
|
|
18
|
+
node.exclamationToken,
|
|
19
|
+
node.type,
|
|
20
|
+
node.initializer
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return ts.visitEachChild(node, (child) => visit(child), context);
|
|
25
|
+
};
|
|
26
|
+
return (node) => ts.visitNode(node, visit);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
Binary file
|