ts-const-value-transformer 0.8.2 → 0.9.0
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/CHANGELOG.md +4 -0
- package/README.md +11 -0
- package/dist/createPortalTransformer.mjs +4 -14
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/transform.d.mts +2 -0
- package/dist/transform.mjs +175 -31
- package/dist/version.d.mts +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -260,6 +260,17 @@ Prints (generates) source code from `SourceFile`, along with raw source-map data
|
|
|
260
260
|
- `originalSourceName` would be the file name of `sourceFile`, but you can specify another name.
|
|
261
261
|
- `startOfSourceMap` is a base source map (if original source file is a generated-content) if available.
|
|
262
262
|
|
|
263
|
+
#### transformAndPrintSource: (sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, options?: TransformOptions) => string
|
|
264
|
+
|
|
265
|
+
Transforms the source file with TypeScript project and prints a new source code. This acts like combination of `transformSource` and `printSource`, but performs in one loop, so if transformed AST is not necessary, this function is suitable.
|
|
266
|
+
|
|
267
|
+
#### transformAndPrintSourceWithMap: (sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, originalSourceName: string, options?: TransformOptions, startOfSourceMap?: RawSourceMap) => [string, RawSourceMap]
|
|
268
|
+
|
|
269
|
+
Transforms the source file with TypeScript project and prints a new source code. This acts like combination of `transformSource` and `printSourceWithMap`, but performs in one loop, so if transformed AST is not necessary, this function is suitable.
|
|
270
|
+
|
|
271
|
+
- `originalSourceName` would be the file name of `sourceFile`, but you can specify another name.
|
|
272
|
+
- `startOfSourceMap` is a base source map (if original source file is a generated-content) if available.
|
|
273
|
+
|
|
263
274
|
#### transformSource: (sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext, options?: TransformOptions) => ts.SourceFile
|
|
264
275
|
|
|
265
276
|
Transforms the source file with TypeScript project. You don't need to call this function directly; use `createTransformer` or `createPortalTransformer` instead.
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
-
import
|
|
5
|
-
import { getIgnoreFilesFunction, printSourceWithMap, } from './transform.mjs';
|
|
4
|
+
import { getIgnoreFilesFunction, transformAndPrintSourceWithMap, } from './transform.mjs';
|
|
6
5
|
const require = createRequire(import.meta.url);
|
|
7
6
|
function optionsToString(options) {
|
|
8
7
|
return JSON.stringify(options, (key, value) => {
|
|
@@ -105,18 +104,9 @@ function createPortalTransformerImpl(options, ts) {
|
|
|
105
104
|
});
|
|
106
105
|
sourceFile.text = content;
|
|
107
106
|
}
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const transformResult = ts.transform(sourceFile, [transformer], program.getCompilerOptions());
|
|
112
|
-
const transformedSource = transformResult.transformed[0];
|
|
113
|
-
let result;
|
|
114
|
-
// If unchanged, return base file as-is
|
|
115
|
-
if (transformedSource === sourceFile) {
|
|
116
|
-
result = [content ?? sourceFile.text, rawSourceMap];
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
result = printSourceWithMap(transformedSource, fileName, rawSourceMap, ts);
|
|
107
|
+
const result = transformAndPrintSourceWithMap(sourceFile, program, undefined, fileName, { ...options, ...individualOptions, ts }, rawSourceMap);
|
|
108
|
+
if (sourceFile.text === result[0]) {
|
|
109
|
+
result[1] = undefined;
|
|
120
110
|
}
|
|
121
111
|
if (cacheResult) {
|
|
122
112
|
// This forces to concatenate strings into flatten one, to reduce object trees for ConsString
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import createPortalTransformer, { createPortalTransformerSync, type CreatePortalTransformerOptions, type PortalTransformer, type PortalTransformerResult, type PortalTransformerResultNonNull } from './createPortalTransformer.mjs';
|
|
2
2
|
import createTransformer from './createTransformer.mjs';
|
|
3
3
|
import version from './version.mjs';
|
|
4
|
-
export { printSource, printSourceWithMap, transformSource, type TransformOptions, } from './transform.mjs';
|
|
4
|
+
export { printSource, printSourceWithMap, transformAndPrintSource, transformAndPrintSourceWithMap, transformSource, type TransformOptions, } from './transform.mjs';
|
|
5
5
|
export { createPortalTransformer, createPortalTransformerSync, createTransformer, type CreatePortalTransformerOptions, type PortalTransformer, type PortalTransformerResult, type PortalTransformerResultNonNull, version, };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import createPortalTransformer, { createPortalTransformerSync, } from './createPortalTransformer.mjs';
|
|
2
2
|
import createTransformer from './createTransformer.mjs';
|
|
3
3
|
import version from './version.mjs';
|
|
4
|
-
export { printSource, printSourceWithMap, transformSource, } from './transform.mjs';
|
|
4
|
+
export { printSource, printSourceWithMap, transformAndPrintSource, transformAndPrintSourceWithMap, transformSource, } from './transform.mjs';
|
|
5
5
|
export { createPortalTransformer, createPortalTransformerSync, createTransformer, version, };
|
package/dist/transform.d.mts
CHANGED
|
@@ -39,3 +39,5 @@ export declare function getIgnoreFilesFunction(ignoreFiles: TransformOptions['ig
|
|
|
39
39
|
export declare function transformSource(sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, options?: TransformOptions): ts.SourceFile;
|
|
40
40
|
export declare function printSource(sourceFile: ts.SourceFile, tsInstance?: typeof ts): string;
|
|
41
41
|
export declare function printSourceWithMap(sourceFile: ts.SourceFile, originalSourceName: string, startOfSourceMap?: sourceMap.RawSourceMap, tsInstance?: typeof ts): [string, sourceMap.RawSourceMap];
|
|
42
|
+
export declare function transformAndPrintSource(sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, options?: TransformOptions): string;
|
|
43
|
+
export declare function transformAndPrintSourceWithMap(sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, originalSourceName: string, options?: TransformOptions, startOfSourceMap?: sourceMap.RawSourceMap): [string, sourceMap.RawSourceMap];
|
package/dist/transform.mjs
CHANGED
|
@@ -41,25 +41,44 @@ export function getIgnoreFilesFunction(ignoreFiles) {
|
|
|
41
41
|
////////////////////////////////////////////////////////////////////////////////
|
|
42
42
|
export function transformSource(sourceFile, program, context, options) {
|
|
43
43
|
const requiredOptions = assignDefaultValues(options);
|
|
44
|
-
|
|
44
|
+
const ts = requiredOptions.ts;
|
|
45
|
+
return ts.visitEachChild(sourceFile, (node) => visitNodeChildren(node, sourceFile, sourceFile, program, requiredOptions, context, (node) => {
|
|
46
|
+
// skip statements which would not have 'value' expressions
|
|
47
|
+
if (ts.isInterfaceDeclaration(node) ||
|
|
48
|
+
ts.isTypeAliasDeclaration(node) ||
|
|
49
|
+
// Identifies in import clause should not be parsed
|
|
50
|
+
ts.isImportDeclaration(node) ||
|
|
51
|
+
ts.isTypeOnlyExportDeclaration(node)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}), context);
|
|
45
56
|
}
|
|
46
|
-
function visitNodeChildren(node, parent, sourceFile, program, options, context) {
|
|
57
|
+
function visitNodeChildren(node, parent, sourceFile, program, options, context, fnVisit, visitContext, fnVisitBeforeReplace, fnVisitBeforeChild, fnVisitAfterChild, fnReplace) {
|
|
47
58
|
const ts = options.ts;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
if (fnVisitBeforeReplace) {
|
|
60
|
+
fnVisitBeforeReplace(node, parent, visitContext);
|
|
61
|
+
}
|
|
62
|
+
const newNode = visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options, context, visitContext, fnReplace ?? 'create');
|
|
63
|
+
if (newNode == null) {
|
|
64
|
+
return node;
|
|
51
65
|
}
|
|
52
|
-
|
|
53
|
-
if (ts.isInterfaceDeclaration(newNode) ||
|
|
54
|
-
ts.isTypeAliasDeclaration(newNode) ||
|
|
55
|
-
// Identifies in import clause should not be parsed
|
|
56
|
-
ts.isImportDeclaration(newNode) ||
|
|
57
|
-
ts.isTypeOnlyExportDeclaration(newNode)) {
|
|
66
|
+
if (newNode !== node) {
|
|
58
67
|
return newNode;
|
|
59
68
|
}
|
|
60
|
-
|
|
69
|
+
if (!fnVisit(node, parent, visitContext)) {
|
|
70
|
+
return node;
|
|
71
|
+
}
|
|
72
|
+
const childVisitContext = fnVisitBeforeChild
|
|
73
|
+
? fnVisitBeforeChild(node, parent, visitContext)
|
|
74
|
+
: visitContext;
|
|
75
|
+
const r = ts.visitEachChild(node, (nodeChild) => visitNodeChildren(nodeChild, node, sourceFile, program, options, context, fnVisit, childVisitContext, fnVisitBeforeReplace, fnVisitBeforeChild, fnVisitAfterChild, fnReplace), context);
|
|
76
|
+
if (fnVisitAfterChild) {
|
|
77
|
+
fnVisitAfterChild(node, parent, childVisitContext);
|
|
78
|
+
}
|
|
79
|
+
return r;
|
|
61
80
|
}
|
|
62
|
-
function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options, context) {
|
|
81
|
+
function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options, context, visitContext, replaceOption) {
|
|
63
82
|
const ts = options.ts;
|
|
64
83
|
if (ts.isCallLikeExpression(node)) {
|
|
65
84
|
if (!ts.isExpression(node) ||
|
|
@@ -127,7 +146,9 @@ function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options,
|
|
|
127
146
|
}
|
|
128
147
|
let newSource;
|
|
129
148
|
if (type.isStringLiteral()) {
|
|
130
|
-
|
|
149
|
+
if (replaceOption === 'create') {
|
|
150
|
+
newNode = ts.factory.createStringLiteral(type.value);
|
|
151
|
+
}
|
|
131
152
|
newSource =
|
|
132
153
|
// TypeScript namespace may export `function escapeNonAsciiString(s: string, quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote | CharacterCodes.backtick): string`
|
|
133
154
|
'escapeNonAsciiString' in ts
|
|
@@ -138,36 +159,50 @@ function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options,
|
|
|
138
159
|
}
|
|
139
160
|
else if (type.isNumberLiteral()) {
|
|
140
161
|
if (type.value < 0) {
|
|
141
|
-
|
|
162
|
+
if (replaceOption === 'create') {
|
|
163
|
+
newNode = ts.factory.createParenthesizedExpression(ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(-type.value)));
|
|
164
|
+
}
|
|
142
165
|
newSource = `(-${-type.value})`;
|
|
143
166
|
}
|
|
144
167
|
else {
|
|
145
|
-
|
|
168
|
+
if (replaceOption === 'create') {
|
|
169
|
+
newNode = ts.factory.createNumericLiteral(type.value);
|
|
170
|
+
}
|
|
146
171
|
newSource = `${type.value}`;
|
|
147
172
|
}
|
|
148
173
|
}
|
|
149
174
|
else if (flags & ts.TypeFlags.BigIntLiteral) {
|
|
150
175
|
const text = typeChecker.typeToString(type);
|
|
151
|
-
|
|
176
|
+
if (replaceOption === 'create') {
|
|
177
|
+
newNode = ts.factory.createBigIntLiteral(text);
|
|
178
|
+
}
|
|
152
179
|
newSource = text;
|
|
153
180
|
}
|
|
154
181
|
else if (flags & ts.TypeFlags.BooleanLiteral) {
|
|
155
182
|
const text = typeChecker.typeToString(type);
|
|
156
|
-
|
|
157
|
-
|
|
183
|
+
if (replaceOption === 'create') {
|
|
184
|
+
newNode =
|
|
185
|
+
text === 'true' ? ts.factory.createTrue() : ts.factory.createFalse();
|
|
186
|
+
}
|
|
158
187
|
newSource = text;
|
|
159
188
|
}
|
|
160
189
|
else if (flags & ts.TypeFlags.Null) {
|
|
161
|
-
|
|
190
|
+
if (replaceOption === 'create') {
|
|
191
|
+
newNode = ts.factory.createNull();
|
|
192
|
+
}
|
|
162
193
|
newSource = 'null';
|
|
163
194
|
}
|
|
164
195
|
else if (flags & ts.TypeFlags.Undefined) {
|
|
165
196
|
if (options.useUndefinedSymbolForUndefinedValue) {
|
|
166
|
-
|
|
197
|
+
if (replaceOption === 'create') {
|
|
198
|
+
newNode = ts.factory.createIdentifier('undefined');
|
|
199
|
+
}
|
|
167
200
|
newSource = 'undefined';
|
|
168
201
|
}
|
|
169
202
|
else {
|
|
170
|
-
|
|
203
|
+
if (replaceOption === 'create') {
|
|
204
|
+
newNode = ts.factory.createParenthesizedExpression(ts.factory.createVoidZero());
|
|
205
|
+
}
|
|
171
206
|
newSource = '(void 0)';
|
|
172
207
|
}
|
|
173
208
|
}
|
|
@@ -176,19 +211,28 @@ function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options,
|
|
|
176
211
|
}
|
|
177
212
|
const originalSource = node.getText(sourceFile);
|
|
178
213
|
const comment = ` ${originalSource.replace(/\/\*/g, ' *').replace(/\*\//g, '* ')} `;
|
|
179
|
-
let result =
|
|
214
|
+
let result = newNode
|
|
215
|
+
? ts.addSyntheticTrailingComment(newNode, ts.SyntaxKind.MultiLineCommentTrivia, comment)
|
|
216
|
+
: undefined;
|
|
180
217
|
newSource = `${newSource} /*${comment}*/`;
|
|
181
218
|
if (/[\r\n]/m.test(originalSource)) {
|
|
182
|
-
|
|
219
|
+
if (result) {
|
|
220
|
+
result = ts.factory.createParenthesizedExpression(result);
|
|
221
|
+
}
|
|
183
222
|
newSource = `(${newSource})`;
|
|
184
223
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
224
|
+
if (result) {
|
|
225
|
+
ts.setTextRange(result, node);
|
|
226
|
+
result[SYMBOL_ORIGINAL_NODE_DATA] = [
|
|
227
|
+
originalSource,
|
|
228
|
+
newSource,
|
|
229
|
+
node.pos,
|
|
230
|
+
node.end,
|
|
231
|
+
];
|
|
232
|
+
}
|
|
233
|
+
if (replaceOption !== 'create') {
|
|
234
|
+
replaceOption(newSource, originalSource, node.pos, node.end, visitContext);
|
|
235
|
+
}
|
|
192
236
|
return result;
|
|
193
237
|
}
|
|
194
238
|
catch {
|
|
@@ -494,3 +538,103 @@ function printNode(tsInstance, baseSource, sourceFile, node, posContext, origina
|
|
|
494
538
|
}
|
|
495
539
|
}
|
|
496
540
|
}
|
|
541
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
542
|
+
export function transformAndPrintSource(sourceFile, program, context, options) {
|
|
543
|
+
return transformAndPrintSourceImpl(sourceFile, program, context, options)[0];
|
|
544
|
+
}
|
|
545
|
+
export function transformAndPrintSourceWithMap(sourceFile, program, context, originalSourceName, options, startOfSourceMap) {
|
|
546
|
+
const generator = new sourceMap.SourceMapGenerator(startOfSourceMap);
|
|
547
|
+
return transformAndPrintSourceImpl(sourceFile, program, context, options, originalSourceName, generator);
|
|
548
|
+
}
|
|
549
|
+
function transformAndPrintSourceImpl(sourceFile, program, context, options, originalSourceName, mapGenerator) {
|
|
550
|
+
const requiredOptions = assignDefaultValues(options);
|
|
551
|
+
if (mapGenerator) {
|
|
552
|
+
mapGenerator.setSourceContent(originalSourceName, sourceFile.getFullText());
|
|
553
|
+
}
|
|
554
|
+
const r = transformAndPrintNode({ pos: 0, diff: 0, lastLine: 0 }, sourceFile.getFullText(), sourceFile, program, context, requiredOptions, originalSourceName, mapGenerator);
|
|
555
|
+
return [r, mapGenerator?.toJSON()];
|
|
556
|
+
}
|
|
557
|
+
function transformAndPrintNode(posContext, baseSource, sourceFile, program, context, options, originalSourceName, mapGenerator) {
|
|
558
|
+
let output = '';
|
|
559
|
+
visitNodeChildren(sourceFile, sourceFile, sourceFile, program, options, context,
|
|
560
|
+
// fnVisit
|
|
561
|
+
(child, _parent, visitContext) => {
|
|
562
|
+
visitContext.lastChildPos = child.end;
|
|
563
|
+
return true;
|
|
564
|
+
},
|
|
565
|
+
// visitContext
|
|
566
|
+
{
|
|
567
|
+
headPrinted: false,
|
|
568
|
+
lastChildPos: 0,
|
|
569
|
+
},
|
|
570
|
+
// fnVisitBeforeReplace
|
|
571
|
+
(child, parent, visitContext) => {
|
|
572
|
+
if (!visitContext.headPrinted) {
|
|
573
|
+
visitContext.headPrinted = true;
|
|
574
|
+
if (child.pos > parent.pos) {
|
|
575
|
+
const text = baseSource.substring(parent.pos, child.pos);
|
|
576
|
+
output += text;
|
|
577
|
+
posContext.pos = child.pos;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else if (child.pos > visitContext.lastChildPos) {
|
|
581
|
+
const text = baseSource.substring(visitContext.lastChildPos, child.pos);
|
|
582
|
+
output += text;
|
|
583
|
+
posContext.pos = child.pos;
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
// fnVisitBeforeChild
|
|
587
|
+
() => {
|
|
588
|
+
return {
|
|
589
|
+
headPrinted: false,
|
|
590
|
+
lastChildPos: 0,
|
|
591
|
+
};
|
|
592
|
+
},
|
|
593
|
+
// fnVisitAfterChild
|
|
594
|
+
(node, _parent, childVisitContext) => {
|
|
595
|
+
if (!childVisitContext.headPrinted) {
|
|
596
|
+
output += baseSource.substring(node.pos, node.end);
|
|
597
|
+
posContext.pos = node.end;
|
|
598
|
+
}
|
|
599
|
+
else if (childVisitContext.lastChildPos < node.end) {
|
|
600
|
+
const text = baseSource.substring(childVisitContext.lastChildPos, node.end);
|
|
601
|
+
output += text;
|
|
602
|
+
posContext.pos = node.end;
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
// fnReplace
|
|
606
|
+
(newSource, originalSource, pos, end, visitContext) => {
|
|
607
|
+
const oldFull = baseSource.substring(pos, end);
|
|
608
|
+
const i = oldFull.lastIndexOf(originalSource);
|
|
609
|
+
const leadingUnchanged = i < 0 ? 0 : i;
|
|
610
|
+
const newText = i < 0
|
|
611
|
+
? newSource
|
|
612
|
+
: oldFull.substring(0, i) +
|
|
613
|
+
newSource +
|
|
614
|
+
oldFull.substring(i + originalSource.length);
|
|
615
|
+
posContext.pos = pos + leadingUnchanged;
|
|
616
|
+
addMappingForCurrent(originalSource);
|
|
617
|
+
posContext.diff += newSource.length - originalSource.length;
|
|
618
|
+
posContext.pos += originalSource.length;
|
|
619
|
+
addMappingForCurrent();
|
|
620
|
+
posContext.pos = end;
|
|
621
|
+
output += newText;
|
|
622
|
+
visitContext.lastChildPos = end;
|
|
623
|
+
});
|
|
624
|
+
return output;
|
|
625
|
+
function addMappingForCurrent(name) {
|
|
626
|
+
const original = positionToLineAndColumn(sourceFile, posContext.pos, 0);
|
|
627
|
+
if (original.line !== posContext.lastLine) {
|
|
628
|
+
posContext.diff = 0;
|
|
629
|
+
posContext.lastLine = original.line;
|
|
630
|
+
}
|
|
631
|
+
if (mapGenerator) {
|
|
632
|
+
mapGenerator.addMapping({
|
|
633
|
+
original,
|
|
634
|
+
generated: positionToLineAndColumn(sourceFile, posContext.pos, posContext.diff),
|
|
635
|
+
source: originalSourceName,
|
|
636
|
+
name,
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
package/dist/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "0.
|
|
1
|
+
declare const _default: "0.9.0";
|
|
2
2
|
export default _default;
|
package/dist/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '0.
|
|
1
|
+
export default '0.9.0';
|