@litsx/babel-preset-litsx 0.1.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/README.md +37 -0
- package/dist/index.cjs +30 -0
- package/dist/index.cjs.map +1 -0
- package/dist/internal/transform-litsx-components.cjs +2518 -0
- package/dist/internal/transform-litsx-components.cjs.map +1 -0
- package/dist/internal/transform-litsx-dom-refs.cjs +16 -0
- package/dist/internal/transform-litsx-dom-refs.cjs.map +1 -0
- package/dist/internal/transform-litsx-hooks.cjs +45 -0
- package/dist/internal/transform-litsx-hooks.cjs.map +1 -0
- package/dist/internal/transform-litsx-properties.cjs +1254 -0
- package/dist/internal/transform-litsx-properties.cjs.map +1 -0
- package/dist/pipeline.cjs +97 -0
- package/dist/pipeline.cjs.map +1 -0
- package/package.json +80 -0
- package/src/index.js +15 -0
- package/src/internal/transform-litsx-class-generation.js +109 -0
- package/src/internal/transform-litsx-components.js +549 -0
- package/src/internal/transform-litsx-dom-refs.js +9 -0
- package/src/internal/transform-litsx-handlers.js +220 -0
- package/src/internal/transform-litsx-hooks.js +38 -0
- package/src/internal/transform-litsx-param-rewrites.js +227 -0
- package/src/internal/transform-litsx-program.js +229 -0
- package/src/internal/transform-litsx-properties.js +1246 -0
- package/src/internal/transform-litsx-refs.js +231 -0
- package/src/internal/transform-litsx-static-hoists.js +754 -0
- package/src/internal/transform-litsx-wrapper-utils.js +243 -0
- package/src/pipeline.js +90 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
let t;
|
|
2
|
+
|
|
3
|
+
export function setHandlersBabelTypes(types) {
|
|
4
|
+
t = types;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function isHoistableHandler(exprPath, componentPath) {
|
|
8
|
+
let hoistable = true;
|
|
9
|
+
|
|
10
|
+
exprPath.traverse({
|
|
11
|
+
Identifier(identifierPath) {
|
|
12
|
+
if (!identifierPath.isReferencedIdentifier()) return;
|
|
13
|
+
|
|
14
|
+
const name = identifierPath.node.name;
|
|
15
|
+
const ownBinding = exprPath.scope.getOwnBinding(name);
|
|
16
|
+
if (ownBinding) return;
|
|
17
|
+
|
|
18
|
+
const binding = identifierPath.scope.getBinding(name);
|
|
19
|
+
if (!binding) return;
|
|
20
|
+
|
|
21
|
+
if (binding.scope === componentPath.scope) {
|
|
22
|
+
hoistable = false;
|
|
23
|
+
identifierPath.stop();
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return hoistable;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function ensureUniqueHandlerName(baseName, usedNames) {
|
|
32
|
+
let candidate = baseName;
|
|
33
|
+
let suffix = 2;
|
|
34
|
+
|
|
35
|
+
while (usedNames.has(candidate)) {
|
|
36
|
+
candidate = `${baseName}${suffix}`;
|
|
37
|
+
suffix += 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
usedNames.add(candidate);
|
|
41
|
+
return candidate;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function generateHandlerName(attrName, usedNames) {
|
|
45
|
+
const eventSegment = attrName.slice(2) || "Event";
|
|
46
|
+
const base = `handle${eventSegment}`;
|
|
47
|
+
return ensureUniqueHandlerName(base, usedNames);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function normalizeHandlerBody(body) {
|
|
51
|
+
if (t.isBlockStatement(body)) {
|
|
52
|
+
return t.cloneNode(body, true);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return t.blockStatement([t.returnStatement(t.cloneNode(body, true))]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function hoistDeclaredHandlers(functionPath, usedNames) {
|
|
59
|
+
const handlerInfos = [];
|
|
60
|
+
const bodyPath = functionPath.get("body");
|
|
61
|
+
if (!bodyPath.isBlockStatement()) {
|
|
62
|
+
return handlerInfos;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
functionPath.traverse({
|
|
66
|
+
VariableDeclarator(path) {
|
|
67
|
+
if (path.getFunctionParent() !== functionPath) return;
|
|
68
|
+
|
|
69
|
+
const id = path.node.id;
|
|
70
|
+
if (!t.isIdentifier(id)) return;
|
|
71
|
+
|
|
72
|
+
const initPath = path.get("init");
|
|
73
|
+
if (!initPath.isArrowFunctionExpression() && !initPath.isFunctionExpression()) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const statementParent = path.getStatementParent();
|
|
78
|
+
if (!statementParent || statementParent.parentPath !== bodyPath) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!isHoistableHandler(initPath, functionPath)) return;
|
|
83
|
+
|
|
84
|
+
const originalName = id.name;
|
|
85
|
+
usedNames.delete(originalName);
|
|
86
|
+
const handlerName = ensureUniqueHandlerName(originalName, usedNames);
|
|
87
|
+
const binding = path.scope.getBinding(originalName);
|
|
88
|
+
|
|
89
|
+
if (!binding) return;
|
|
90
|
+
|
|
91
|
+
binding.referencePaths.slice().forEach((refPath) => {
|
|
92
|
+
if (!refPath.node || refPath.removed) return;
|
|
93
|
+
refPath.replaceWith(
|
|
94
|
+
t.memberExpression(t.thisExpression(), t.identifier(handlerName))
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
handlerInfos.push({
|
|
99
|
+
name: handlerName,
|
|
100
|
+
params: initPath.node.params.map((param) => t.cloneNode(param, true)),
|
|
101
|
+
body: normalizeHandlerBody(initPath.node.body),
|
|
102
|
+
async: initPath.node.async,
|
|
103
|
+
generator: initPath.node.generator,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
path.remove();
|
|
107
|
+
|
|
108
|
+
if (
|
|
109
|
+
statementParent.isVariableDeclaration() &&
|
|
110
|
+
statementParent.node.declarations.length === 0
|
|
111
|
+
) {
|
|
112
|
+
statementParent.remove();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
binding.scope.removeBinding(originalName);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return handlerInfos;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function hoistEventHandlers(functionPath, usedNames) {
|
|
123
|
+
const handlerInfos = [];
|
|
124
|
+
|
|
125
|
+
functionPath.traverse({
|
|
126
|
+
JSXAttribute(attrPath) {
|
|
127
|
+
if (attrPath.getFunctionParent() !== functionPath) return;
|
|
128
|
+
|
|
129
|
+
const { node } = attrPath;
|
|
130
|
+
if (!t.isJSXIdentifier(node.name)) return;
|
|
131
|
+
|
|
132
|
+
const attrName = node.name.name;
|
|
133
|
+
if (!/^on[A-Z]/.test(attrName)) return;
|
|
134
|
+
|
|
135
|
+
const valuePath = attrPath.get("value");
|
|
136
|
+
if (!valuePath.isJSXExpressionContainer()) return;
|
|
137
|
+
|
|
138
|
+
const exprPath = valuePath.get("expression");
|
|
139
|
+
if (
|
|
140
|
+
!exprPath.isArrowFunctionExpression() &&
|
|
141
|
+
!exprPath.isFunctionExpression()
|
|
142
|
+
) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!isHoistableHandler(exprPath, functionPath)) return;
|
|
147
|
+
|
|
148
|
+
const handlerName = generateHandlerName(attrName, usedNames);
|
|
149
|
+
|
|
150
|
+
handlerInfos.push({
|
|
151
|
+
name: handlerName,
|
|
152
|
+
params: exprPath.node.params.map((param) => t.cloneNode(param, true)),
|
|
153
|
+
body: normalizeHandlerBody(exprPath.node.body),
|
|
154
|
+
async: exprPath.node.async,
|
|
155
|
+
generator: exprPath.node.generator,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
valuePath.replaceWith(
|
|
159
|
+
t.jsxExpressionContainer(
|
|
160
|
+
t.memberExpression(t.thisExpression(), t.identifier(handlerName))
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return handlerInfos;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function isNativeIntrinsicJsxElement(nameNode) {
|
|
170
|
+
return t.isJSXIdentifier(nameNode) && /^[a-z]/.test(nameNode.name);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function collectNativeClassNameWarnings(functionPath, warn, options = {}) {
|
|
174
|
+
if (typeof warn !== "function" || options.suppressNativeClassNameWarning === true) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
functionPath.traverse({
|
|
179
|
+
JSXAttribute(attrPath) {
|
|
180
|
+
if (attrPath.getFunctionParent() !== functionPath) return;
|
|
181
|
+
|
|
182
|
+
const openingElement = attrPath.parentPath;
|
|
183
|
+
if (!openingElement?.isJSXOpeningElement()) return;
|
|
184
|
+
if (!isNativeIntrinsicJsxElement(openingElement.node.name)) return;
|
|
185
|
+
|
|
186
|
+
const { node } = attrPath;
|
|
187
|
+
if (!t.isJSXIdentifier(node.name, { name: "className" })) return;
|
|
188
|
+
|
|
189
|
+
warn({
|
|
190
|
+
code: "LITSX_NATIVE_CLASSNAME",
|
|
191
|
+
message:
|
|
192
|
+
'`className` is not native LitSX syntax. Use `class` in native LitSX, or add the React compatibility layer to rewrite `className`.',
|
|
193
|
+
attributeName: "className",
|
|
194
|
+
tagName: openingElement.node.name.name,
|
|
195
|
+
line: node.loc?.start?.line ?? null,
|
|
196
|
+
column: node.loc?.start?.column ?? null,
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function processHandlers(functionPath, usedNames) {
|
|
203
|
+
const declaredHandlers = hoistDeclaredHandlers(functionPath, usedNames);
|
|
204
|
+
const inlineHandlers = hoistEventHandlers(functionPath, usedNames);
|
|
205
|
+
return [...declaredHandlers, ...inlineHandlers];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function createHandlerClassMember({ name, params, body, async, generator }) {
|
|
209
|
+
const method = t.classMethod(
|
|
210
|
+
"method",
|
|
211
|
+
t.identifier(name),
|
|
212
|
+
params.map((param) => t.cloneNode(param, true)),
|
|
213
|
+
t.cloneNode(body, true)
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
method.async = Boolean(async);
|
|
217
|
+
method.generator = Boolean(generator);
|
|
218
|
+
|
|
219
|
+
return method;
|
|
220
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createRuntimeHooksTransform } from "@litsx/babel-plugin-shared-hooks";
|
|
2
|
+
|
|
3
|
+
const RUNTIME_MODULE = "litsx";
|
|
4
|
+
const IMPORT_SOURCES = [RUNTIME_MODULE];
|
|
5
|
+
|
|
6
|
+
const RUNTIME_HELPERS = [
|
|
7
|
+
"useOnConnect",
|
|
8
|
+
"useAfterUpdate",
|
|
9
|
+
"useOnCommit",
|
|
10
|
+
"useMemoValue",
|
|
11
|
+
"useStableCallback",
|
|
12
|
+
"useEvent",
|
|
13
|
+
"useEmit",
|
|
14
|
+
"usePrevious",
|
|
15
|
+
"useReducedState",
|
|
16
|
+
"useState",
|
|
17
|
+
"useControlledState",
|
|
18
|
+
"useAsyncState",
|
|
19
|
+
"useOptimistic",
|
|
20
|
+
"useExpose",
|
|
21
|
+
"useExternalStore",
|
|
22
|
+
"useHost",
|
|
23
|
+
"useHostContent",
|
|
24
|
+
"useSlot",
|
|
25
|
+
"useTextContent",
|
|
26
|
+
"useTransition",
|
|
27
|
+
"useDeferredValue",
|
|
28
|
+
"useStyle",
|
|
29
|
+
"useRef",
|
|
30
|
+
"useCallbackRef",
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
export default createRuntimeHooksTransform({
|
|
34
|
+
pluginName: "transform-litsx-hooks",
|
|
35
|
+
runtimeModule: RUNTIME_MODULE,
|
|
36
|
+
importSources: IMPORT_SOURCES,
|
|
37
|
+
helperNames: RUNTIME_HELPERS,
|
|
38
|
+
});
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
let t;
|
|
2
|
+
|
|
3
|
+
export function setParamRewriteBabelTypes(nextTypes) {
|
|
4
|
+
t = nextTypes;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function createThisMemberExpression(propName) {
|
|
8
|
+
return t.memberExpression(t.thisExpression(), t.identifier(propName));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function transformJSXExpressions(jsxPath, bindings) {
|
|
12
|
+
const localNames = Array.from(bindings.keys());
|
|
13
|
+
|
|
14
|
+
jsxPath.traverse({
|
|
15
|
+
JSXExpressionContainer(expressionPath) {
|
|
16
|
+
if (t.isIdentifier(expressionPath.node.expression)) {
|
|
17
|
+
const name = expressionPath.node.expression.name;
|
|
18
|
+
if (localNames.includes(name)) {
|
|
19
|
+
const propName = bindings.get(name) || name;
|
|
20
|
+
expressionPath.node.expression = t.memberExpression(
|
|
21
|
+
t.thisExpression(),
|
|
22
|
+
t.identifier(propName)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function registerLocalPropAliases(functionPath, bindings) {
|
|
31
|
+
let changed = true;
|
|
32
|
+
|
|
33
|
+
while (changed) {
|
|
34
|
+
changed = false;
|
|
35
|
+
|
|
36
|
+
functionPath.traverse({
|
|
37
|
+
VariableDeclarator(path) {
|
|
38
|
+
if (path.getFunctionParent() !== functionPath) return;
|
|
39
|
+
|
|
40
|
+
const { id, init } = path.node;
|
|
41
|
+
if (!t.isIdentifier(init)) return;
|
|
42
|
+
|
|
43
|
+
if (t.isIdentifier(id)) {
|
|
44
|
+
if (bindings.has(id.name) || !bindings.has(init.name)) return;
|
|
45
|
+
bindings.set(id.name, bindings.get(init.name));
|
|
46
|
+
changed = true;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!t.isObjectPattern(id)) return;
|
|
51
|
+
|
|
52
|
+
const bindingInfo = bindings.get(init.name);
|
|
53
|
+
if (!bindingInfo || typeof bindingInfo !== "object" || bindingInfo.kind !== "alias") {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
id.properties.forEach((property) => {
|
|
58
|
+
if (!t.isObjectProperty(property)) return;
|
|
59
|
+
|
|
60
|
+
const keyName = t.isIdentifier(property.key)
|
|
61
|
+
? property.key.name
|
|
62
|
+
: t.isStringLiteral(property.key)
|
|
63
|
+
? property.key.value
|
|
64
|
+
: null;
|
|
65
|
+
|
|
66
|
+
if (!keyName || !bindingInfo.properties.has(keyName)) return;
|
|
67
|
+
|
|
68
|
+
if (t.isIdentifier(property.value)) {
|
|
69
|
+
if (!bindings.has(property.value.name)) {
|
|
70
|
+
bindings.set(property.value.name, keyName);
|
|
71
|
+
changed = true;
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (
|
|
77
|
+
t.isAssignmentPattern(property.value) &&
|
|
78
|
+
t.isIdentifier(property.value.left) &&
|
|
79
|
+
!bindings.has(property.value.left.name)
|
|
80
|
+
) {
|
|
81
|
+
bindings.set(property.value.left.name, keyName);
|
|
82
|
+
changed = true;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function shouldCapturePropReference(refPath, functionPath) {
|
|
91
|
+
const functionParent = refPath.getFunctionParent();
|
|
92
|
+
if (!functionParent || functionParent === functionPath) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return !functionParent.isArrowFunctionExpression();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function replaceParamReferences(functionPath, bindings, propertyMap = new Map()) {
|
|
100
|
+
registerLocalPropAliases(functionPath, bindings);
|
|
101
|
+
|
|
102
|
+
const capturedPropAliases = new Map();
|
|
103
|
+
|
|
104
|
+
function getReplacementForProp(propName, refPath) {
|
|
105
|
+
if (shouldCapturePropReference(refPath, functionPath)) {
|
|
106
|
+
let aliasId = capturedPropAliases.get(propName);
|
|
107
|
+
if (!aliasId) {
|
|
108
|
+
aliasId = functionPath.scope.generateUidIdentifier(propName);
|
|
109
|
+
capturedPropAliases.set(propName, aliasId);
|
|
110
|
+
}
|
|
111
|
+
return t.cloneNode(aliasId);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return t.memberExpression(t.thisExpression(), t.identifier(propName));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
bindings.forEach((bindingInfo, localName) => {
|
|
118
|
+
if (!localName) return;
|
|
119
|
+
const binding = functionPath.scope.getBinding(localName);
|
|
120
|
+
if (!binding) return;
|
|
121
|
+
|
|
122
|
+
binding.referencePaths.slice().forEach((refPath) => {
|
|
123
|
+
if (!refPath.node) return;
|
|
124
|
+
|
|
125
|
+
if (
|
|
126
|
+
bindingInfo &&
|
|
127
|
+
typeof bindingInfo === "object" &&
|
|
128
|
+
bindingInfo.kind === "alias" &&
|
|
129
|
+
(!refPath.parentPath || !refPath.parentPath.isMemberExpression())
|
|
130
|
+
) {
|
|
131
|
+
if (shouldCapturePropReference(refPath, functionPath)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
refPath.parentPath &&
|
|
137
|
+
refPath.parentPath.isObjectProperty({ shorthand: true }) &&
|
|
138
|
+
refPath.parentKey === "value"
|
|
139
|
+
) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
refPath.replaceWith(t.thisExpression());
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (
|
|
148
|
+
bindingInfo &&
|
|
149
|
+
typeof bindingInfo === "object" &&
|
|
150
|
+
bindingInfo.kind === "alias" &&
|
|
151
|
+
refPath.parentPath &&
|
|
152
|
+
refPath.parentPath.isMemberExpression() &&
|
|
153
|
+
refPath.parentKey === "object" &&
|
|
154
|
+
t.isIdentifier(refPath.parentPath.node.property) &&
|
|
155
|
+
!refPath.parentPath.node.computed
|
|
156
|
+
) {
|
|
157
|
+
const propName = refPath.parentPath.node.property.name;
|
|
158
|
+
if (bindingInfo.properties.has(propName)) {
|
|
159
|
+
refPath.parentPath.replaceWith(getReplacementForProp(propName, refPath));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let targetProp;
|
|
165
|
+
if (typeof bindingInfo === "string") {
|
|
166
|
+
targetProp = bindingInfo;
|
|
167
|
+
} else if (bindingInfo && typeof bindingInfo === "object") {
|
|
168
|
+
targetProp = bindingInfo.bindKey;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (
|
|
172
|
+
typeof bindingInfo === "string" &&
|
|
173
|
+
refPath.parentPath &&
|
|
174
|
+
refPath.parentPath.isMemberExpression() &&
|
|
175
|
+
refPath.parentKey === "object" &&
|
|
176
|
+
t.isIdentifier(refPath.parentPath.node.property) &&
|
|
177
|
+
!refPath.parentPath.node.computed
|
|
178
|
+
) {
|
|
179
|
+
const propName = refPath.parentPath.node.property.name;
|
|
180
|
+
if (localName === "props" || propertyMap.has(propName)) {
|
|
181
|
+
refPath.parentPath.replaceWith(getReplacementForProp(propName, refPath));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (
|
|
187
|
+
refPath.parentPath &&
|
|
188
|
+
refPath.parentPath.isObjectProperty({ shorthand: true }) &&
|
|
189
|
+
refPath.parentKey === "value"
|
|
190
|
+
) {
|
|
191
|
+
refPath.parentPath.node.shorthand = false;
|
|
192
|
+
refPath.replaceWith(getReplacementForProp(targetProp || localName, refPath));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
refPath.parentPath &&
|
|
198
|
+
refPath.parentPath.isJSXAttribute() &&
|
|
199
|
+
refPath.parentKey === "value"
|
|
200
|
+
) {
|
|
201
|
+
refPath.replaceWith(
|
|
202
|
+
t.jsxExpressionContainer(
|
|
203
|
+
getReplacementForProp(targetProp || localName, refPath)
|
|
204
|
+
)
|
|
205
|
+
);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (refPath.parentPath && refPath.parentPath.isMemberExpression()) {
|
|
210
|
+
if (
|
|
211
|
+
refPath.parentKey === "property" &&
|
|
212
|
+
!refPath.parentPath.node.computed
|
|
213
|
+
) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
refPath.replaceWith(getReplacementForProp(targetProp || localName, refPath));
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return Array.from(capturedPropAliases.entries()).map(([propName, aliasId]) =>
|
|
223
|
+
t.variableDeclaration("const", [
|
|
224
|
+
t.variableDeclarator(t.cloneNode(aliasId), createThisMemberExpression(propName)),
|
|
225
|
+
])
|
|
226
|
+
);
|
|
227
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
let t;
|
|
2
|
+
|
|
3
|
+
export function setProgramBabelTypes(nextTypes) {
|
|
4
|
+
t = nextTypes;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function createLitElementImport() {
|
|
8
|
+
return t.importDeclaration(
|
|
9
|
+
[
|
|
10
|
+
t.importSpecifier(t.identifier("LitElement"), t.identifier("LitElement")),
|
|
11
|
+
],
|
|
12
|
+
t.stringLiteral("lit")
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function createLitsxInfrastructureImport(importedName) {
|
|
17
|
+
return t.importDeclaration(
|
|
18
|
+
[
|
|
19
|
+
t.importSpecifier(t.identifier(importedName), t.identifier(importedName)),
|
|
20
|
+
],
|
|
21
|
+
t.stringLiteral("litsx/runtime-infrastructure")
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function createLitsxImport(importedName) {
|
|
26
|
+
return t.importDeclaration(
|
|
27
|
+
[
|
|
28
|
+
t.importSpecifier(t.identifier(importedName), t.identifier(importedName)),
|
|
29
|
+
],
|
|
30
|
+
t.stringLiteral("litsx")
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function ensureNamedImport(importPath, importedName) {
|
|
35
|
+
const specifiers = importPath.node.specifiers;
|
|
36
|
+
|
|
37
|
+
if (
|
|
38
|
+
specifiers.some(
|
|
39
|
+
(specifier) =>
|
|
40
|
+
t.isImportSpecifier(specifier) &&
|
|
41
|
+
t.isIdentifier(specifier.imported, { name: importedName })
|
|
42
|
+
)
|
|
43
|
+
) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (specifiers.some((specifier) => t.isImportNamespaceSpecifier(specifier))) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
specifiers.push(
|
|
52
|
+
t.importSpecifier(t.identifier(importedName), t.identifier(importedName))
|
|
53
|
+
);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function pruneUnusedLitsxStaticImports(programPath) {
|
|
58
|
+
programPath.scope.crawl();
|
|
59
|
+
|
|
60
|
+
const bodyPaths = programPath.get("body");
|
|
61
|
+
const litsxImports = bodyPaths.filter(
|
|
62
|
+
(path) => path.isImportDeclaration() && path.node.source.value === "litsx"
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
litsxImports.forEach((importPath) => {
|
|
66
|
+
const removableSpecifiers = importPath.get("specifiers").filter((specifierPath) => {
|
|
67
|
+
if (!specifierPath.isImportSpecifier()) return false;
|
|
68
|
+
if (!t.isIdentifier(specifierPath.node.imported)) return false;
|
|
69
|
+
|
|
70
|
+
const importedName = specifierPath.node.imported.name;
|
|
71
|
+
if (importedName !== "staticStyles" && importedName !== "staticProps") {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const localName = t.isIdentifier(specifierPath.node.local)
|
|
76
|
+
? specifierPath.node.local.name
|
|
77
|
+
: importedName;
|
|
78
|
+
const binding = specifierPath.scope.getBinding(localName);
|
|
79
|
+
return !binding || binding.referencePaths.length === 0;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
removableSpecifiers.forEach((specifierPath) => {
|
|
83
|
+
specifierPath.remove();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (importPath.node.specifiers.length === 0) {
|
|
87
|
+
importPath.remove();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function finalizeProgram(programPath, state) {
|
|
93
|
+
if (!state?.__litsxTransformCount) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const hoistDeclarations = [];
|
|
98
|
+
for (const bodyPath of programPath.get("body")) {
|
|
99
|
+
const node = bodyPath.isClassDeclaration()
|
|
100
|
+
? bodyPath.node
|
|
101
|
+
: bodyPath.isVariableDeclaration()
|
|
102
|
+
? bodyPath.node
|
|
103
|
+
: bodyPath.isExportNamedDeclaration() || bodyPath.isExportDefaultDeclaration()
|
|
104
|
+
? bodyPath.node.declaration
|
|
105
|
+
: null;
|
|
106
|
+
|
|
107
|
+
if (!node) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (t.isClassDeclaration(node) && Array.isArray(node._litsxStaticSymbolDeclarations)) {
|
|
112
|
+
hoistDeclarations.push(...node._litsxStaticSymbolDeclarations);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (t.isVariableDeclaration(node)) {
|
|
117
|
+
node.declarations.forEach((declarator) => {
|
|
118
|
+
if (Array.isArray(declarator.init?._litsxStaticSymbolDeclarations)) {
|
|
119
|
+
hoistDeclarations.push(...declarator.init._litsxStaticSymbolDeclarations);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (hoistDeclarations.length > 0) {
|
|
126
|
+
programPath.unshiftContainer("body", hoistDeclarations);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const bodyPaths = programPath.get("body");
|
|
130
|
+
const litImports = bodyPaths.filter(
|
|
131
|
+
(n) => n.isImportDeclaration() && n.node.source.value === "lit"
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
let litElementImported = false;
|
|
135
|
+
|
|
136
|
+
litImports.some((importPath) => {
|
|
137
|
+
if (ensureNamedImport(importPath, "LitElement")) {
|
|
138
|
+
litElementImported = true;
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return false;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (!litElementImported) {
|
|
146
|
+
programPath.unshiftContainer("body", createLitElementImport());
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (state.__litsxNeedsCss) {
|
|
150
|
+
const nextBodyPaths = programPath.get("body");
|
|
151
|
+
const nextLitImports = nextBodyPaths.filter(
|
|
152
|
+
(n) => n.isImportDeclaration() && n.node.source.value === "lit"
|
|
153
|
+
);
|
|
154
|
+
nextLitImports.some((importPath) => ensureNamedImport(importPath, "css"));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (state.__litsxNeedsUnsafeCss) {
|
|
158
|
+
const nextBodyPaths = programPath.get("body");
|
|
159
|
+
const nextLitImports = nextBodyPaths.filter(
|
|
160
|
+
(n) => n.isImportDeclaration() && n.node.source.value === "lit"
|
|
161
|
+
);
|
|
162
|
+
nextLitImports.some((importPath) => ensureNamedImport(importPath, "unsafeCSS"));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (state.__litsxNeedsStaticHoistsMixin) {
|
|
166
|
+
const bodyPathsWithInternal = programPath.get("body");
|
|
167
|
+
const internalImports = bodyPathsWithInternal.filter(
|
|
168
|
+
(n) => n.isImportDeclaration() && n.node.source.value === "litsx/runtime-infrastructure"
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
let internalImported = false;
|
|
172
|
+
internalImports.some((importPath) => {
|
|
173
|
+
if (ensureNamedImport(importPath, "LitsxStaticHoistsMixin")) {
|
|
174
|
+
internalImported = true;
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return false;
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
if (!internalImported) {
|
|
182
|
+
programPath.unshiftContainer("body", createLitsxInfrastructureImport("LitsxStaticHoistsMixin"));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (state.__litsxNeedsLightDomMixin) {
|
|
187
|
+
const bodyPathsWithInternal = programPath.get("body");
|
|
188
|
+
const internalImports = bodyPathsWithInternal.filter(
|
|
189
|
+
(n) => n.isImportDeclaration() && n.node.source.value === "litsx/runtime-infrastructure"
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
let internalImported = false;
|
|
193
|
+
internalImports.some((importPath) => {
|
|
194
|
+
if (ensureNamedImport(importPath, "LightDomMixin")) {
|
|
195
|
+
internalImported = true;
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return false;
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
if (!internalImported) {
|
|
203
|
+
programPath.unshiftContainer("body", createLitsxInfrastructureImport("LightDomMixin"));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (state.__litsxNeedsCallbackRef) {
|
|
208
|
+
const bodyPathsWithLitsx = programPath.get("body");
|
|
209
|
+
const litsxImports = bodyPathsWithLitsx.filter(
|
|
210
|
+
(n) => n.isImportDeclaration() && n.node.source.value === "litsx"
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
let litsxImported = false;
|
|
214
|
+
litsxImports.some((importPath) => {
|
|
215
|
+
if (ensureNamedImport(importPath, "useCallbackRef")) {
|
|
216
|
+
litsxImported = true;
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return false;
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
if (!litsxImported) {
|
|
224
|
+
programPath.unshiftContainer("body", createLitsxImport("useCallbackRef"));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
pruneUnusedLitsxStaticImports(programPath);
|
|
229
|
+
}
|