Skip to content

Commit 18d57f0

Browse files
committed
feat: support TemplateExpression
1 parent 4298015 commit 18d57f0

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

src/transform-node.ts

Lines changed: 69 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,54 @@ 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+
const start = isFirst
563+
? templateLiteral.sourceSpan.start + 1
564+
: node.sourceSpan.start;
565+
566+
let end;
567+
if (isLast) {
568+
end = templateLiteral.sourceSpan.end - 1;
569+
} else {
570+
const nextExpression = templateLiteral.expressions[elementIndex];
571+
end = this.getCharacterLastIndex('$', nextExpression.sourceSpan.start);
572+
}
573+
const raw = this.text.slice(start, end);
574+
575+
return this.#create<babel.TemplateElement>(
576+
{
577+
type: 'TemplateElement',
578+
value: {
579+
cooked: node.text,
580+
raw,
581+
},
582+
start: start,
583+
end: end,
584+
tail: isLast,
585+
},
586+
{ stripSpaces: false },
587+
);
588+
}
589+
526590
// istanbul ignore next
527591
throw Object.assign(new Error('Unexpected node'), { node });
528592
}

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)