/
transform-in-element.ts
120 lines (100 loc) · 3.65 KB
/
transform-in-element.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { assert, deprecate } from '@ember/debug';
import { AST, ASTPlugin } from '@glimmer/syntax';
import calculateLocationDisplay from '../system/calculate-location-display';
import { EmberASTPluginEnvironment } from '../types';
import { isPath } from './utils';
/**
@module ember
*/
/**
A Glimmer2 AST transformation that handles the public `{{in-element}}` as per RFC287, and deprecates but still
continues support for the private `{{-in-element}}`.
Transforms:
```handlebars
{{#-in-element someElement}}
{{modal-display text=text}}
{{/-in-element}}
```
into:
```handlebars
{{#in-element someElement}}
{{modal-display text=text}}
{{/in-element}}
```
And issues a deprecation message.
Issues a build time assertion for:
```handlebars
{{#in-element someElement insertBefore="some-none-null-value"}}
{{modal-display text=text}}
{{/in-element}}
```
@private
@class TransformInElement
*/
export default function transformInElement(env: EmberASTPluginEnvironment): ASTPlugin {
let moduleName = env.meta?.moduleName;
let { builders: b } = env.syntax;
return {
name: 'transform-in-element',
visitor: {
BlockStatement(node: AST.BlockStatement) {
if (!isPath(node.path)) return;
if (node.path.original === 'in-element') {
let originalValue = node.params[0];
if (originalValue && !env.isProduction) {
let subExpr = b.sexpr('-in-el-null', [originalValue]);
node.params.shift();
node.params.unshift(subExpr);
}
node.hash.pairs.forEach((pair) => {
if (pair.key === 'insertBefore') {
assert(
`Can only pass null to insertBefore in in-element, received: ${JSON.stringify(
pair.value
)}`,
pair.value.type === 'NullLiteral' || pair.value.type === 'UndefinedLiteral'
);
}
});
} else if (node.path.original === '-in-element') {
let sourceInformation = calculateLocationDisplay(moduleName, node.loc);
deprecate(
`The use of the private \`{{-in-element}}\` is deprecated, please refactor to the public \`{{in-element}}\`. ${sourceInformation}`,
false,
{
id: 'glimmer.private-in-element',
until: '3.25.0',
for: 'ember-source',
since: {
enabled: '3.20.0',
},
}
);
node.path.original = 'in-element';
node.path.parts = ['in-element'];
// replicate special hash arguments added here:
// https://github.com/glimmerjs/glimmer-vm/blob/ba9b37d44b85fa1385eeeea71910ff5798198c8e/packages/%40glimmer/syntax/lib/parser/handlebars-node-visitors.ts#L340-L363
let needsInsertBefore = true;
let hash = node.hash;
hash.pairs.forEach((pair) => {
if (pair.key === 'insertBefore') {
assert(
`Can only pass a null or undefined literals to insertBefore in -in-element, received: ${JSON.stringify(
pair.value
)}`,
pair.value.type === 'NullLiteral' || pair.value.type === 'UndefinedLiteral'
);
needsInsertBefore = false;
}
});
// Maintain compatibility with previous -in-element behavior (defaults to append, not clear)
if (needsInsertBefore) {
let nullLiteral = b.literal('NullLiteral', null);
let nextSibling = b.pair('insertBefore', nullLiteral);
hash.pairs.push(nextSibling);
}
}
},
},
};
}