Skip to content

Commit bfa66eb

Browse files
committed
feat: support TemplateExpression
1 parent 4298015 commit bfa66eb

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

src/transform-node.ts

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ function isImplicitThis(node: angular.AST, text: string): boolean {
3434
return start >= end || /^\s+$/.test(text.slice(start, end));
3535
}
3636

37+
type NodeTransformOptions = {
38+
isInParentParens?: boolean;
39+
parent?: angular.AST;
40+
};
41+
3742
class Transformer extends Source {
3843
#node;
3944
#text;
@@ -105,12 +110,19 @@ class Transformer extends Source {
105110
);
106111
}
107112

108-
#transform<T extends NGNode>(node: angular.AST, isInParentParens = false) {
109-
return this.#transformNode(node, isInParentParens) as T &
110-
LocationInformation;
113+
#transform<T extends NGNode>(
114+
node: angular.AST,
115+
options?: NodeTransformOptions,
116+
) {
117+
return this.#transformNode(node, options) as T & LocationInformation;
111118
}
112119

113-
#transformNode(node: angular.AST, isInParentParens = false): NGNode {
120+
#transformNode(node: angular.AST, options?: NodeTransformOptions): NGNode {
121+
const { isInParentParens } = {
122+
isInParentParens: false,
123+
...options,
124+
};
125+
114126
if (node instanceof angular.Interpolation) {
115127
const { expressions } = node;
116128

@@ -374,7 +386,11 @@ class Transformer extends Source {
374386
const { receiver, args } = node;
375387
const tArgs =
376388
args.length === 1
377-
? [this.#transform<babel.Expression>(args[0], true)]
389+
? [
390+
this.#transform<babel.Expression>(args[0], {
391+
isInParentParens: true,
392+
}),
393+
]
378394
: (args as angular.AST[]).map<babel.Expression>((node) =>
379395
this.#transform(node),
380396
);
@@ -523,6 +539,55 @@ class Transformer extends Source {
523539
);
524540
}
525541

542+
if (node instanceof angular.TemplateLiteral) {
543+
const { elements, expressions } = node;
544+
545+
return this.#create<babel.TemplateLiteral>({
546+
type: 'TemplateLiteral',
547+
quasis: elements.map((element) =>
548+
this.#transform(element, { parent: node }),
549+
),
550+
expressions: expressions.map((expression) =>
551+
this.#transform(expression),
552+
),
553+
...node.sourceSpan,
554+
});
555+
}
556+
557+
if (node instanceof angular.TemplateLiteralElement) {
558+
const templateLiteral = options!.parent! as angular.TemplateLiteral;
559+
const elementIndex = templateLiteral.elements.indexOf(node);
560+
const isFirst = elementIndex === 0;
561+
const isLast = elementIndex === templateLiteral.elements.length - 1;
562+
563+
// The `TemplateLiteralElement` don't have correct location information
564+
const start = isFirst
565+
? templateLiteral.sourceSpan.start + 1
566+
: node.sourceSpan.start;
567+
let end;
568+
if (isLast) {
569+
end = templateLiteral.sourceSpan.end - 1;
570+
} else {
571+
const nextExpression = templateLiteral.expressions[elementIndex];
572+
end = this.getCharacterLastIndex('$', nextExpression.sourceSpan.start);
573+
}
574+
const raw = this.text.slice(start, end);
575+
576+
return this.#create<babel.TemplateElement>(
577+
{
578+
type: 'TemplateElement',
579+
value: {
580+
cooked: node.text,
581+
raw,
582+
},
583+
start: start,
584+
end: end,
585+
tail: isLast,
586+
},
587+
{ stripSpaces: false },
588+
);
589+
}
590+
526591
// istanbul ignore next
527592
throw Object.assign(new Error('Unexpected node'), { node });
528593
}

tests/transform.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ describe.each`
9494
${'TypeofExpression'} | ${'UnaryExpression'} | ${' typeof {} '} | ${true} | ${true} | ${true} | ${true}
9595
${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true}
9696
${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "number" ) '} | ${true} | ${true} | ${true} | ${true}
97+
${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true}
98+
${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ` a ${ b } \u0063 ` ) '} | ${true} | ${true} | ${true} | ${true}
9799
`('($expectedAngularType -> $expectedEstreeType)', (fields) => {
98100
for (const method of PARSE_METHODS) {
99101
testSection(method, fields);

0 commit comments

Comments
 (0)