unplugin-zed-gpui 0.0.3 → 0.0.5

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/dist/index.cjs CHANGED
@@ -85,14 +85,14 @@ const zedGpuiPlugin = (0, unplugin.createUnplugin)((options = {}) => {
85
85
  return {
86
86
  name: "unplugin-zed-gpui",
87
87
  transform(code, id) {
88
- if (hasElementPrototypeAssign(code)) {
88
+ if (shouldProcessFile(id)) analyzeUsage(code, usedMethods, opts);
89
+ if (hasPrototypeEnhancement(code)) {
89
90
  if (opts.debug) {
90
91
  console.log(`[zed-gpui] Processing element file: ${id}`);
91
92
  console.log(`[zed-gpui] Used methods:`, formatUsedMethods(usedMethods));
92
93
  }
93
94
  return transformElementFile(code, usedMethods, opts);
94
95
  }
95
- if (shouldProcessFile(id)) analyzeUsage(code, usedMethods, opts);
96
96
  return null;
97
97
  },
98
98
  buildEnd() {
@@ -139,8 +139,8 @@ function analyzeUsage(code, usedMethods, options) {
139
139
  function hasZedGpuiUsage(code) {
140
140
  return /\.\s*([a-z_][a-zA-Z0-9_]*)\s*\(/.test(code);
141
141
  }
142
- function hasElementPrototypeAssign(code) {
143
- return code.includes("Object.assign") && /HTML[A-Za-z]*Element\.prototype/.test(code);
142
+ function hasPrototypeEnhancement(code) {
143
+ return code.includes("$_(") && /HTML[A-Za-z]*Element/.test(code);
144
144
  }
145
145
  /**
146
146
  * Recursively scan AST nodes for method calls
@@ -203,15 +203,20 @@ function addUsedMethod(usedMethods, elementType, methodName) {
203
203
  function inferElementType(node, bindings) {
204
204
  if (_babel_types.isIdentifier(node)) return bindings.get(node.name);
205
205
  if (_babel_types.isTSAsExpression(node) || _babel_types.isTSTypeAssertion(node)) return getElementTypeFromTsType(node.typeAnnotation) ?? inferElementType(node.expression, bindings);
206
+ if (_babel_types.isTSNonNullExpression(node)) return inferElementType(node.expression, bindings);
206
207
  if (_babel_types.isCallExpression(node)) {
208
+ if (_babel_types.isMemberExpression(node.callee)) {
209
+ if (_babel_types.isIdentifier(node.callee.object, { name: "document" }) && (_babel_types.isIdentifier(node.callee.property, { name: "querySelector" }) || _babel_types.isIdentifier(node.callee.property, { name: "getElementById" }))) {
210
+ const typeArg = node.typeArguments?.params[0];
211
+ return typeArg && _babel_types.isTSType(typeArg) ? getElementTypeFromTsType(typeArg) : "HTMLElement";
212
+ }
213
+ if (_babel_types.isIdentifier(node.callee.property, { name: "createElement" }) && _babel_types.isIdentifier(node.callee.object, { name: "document" }) && _babel_types.isStringLiteral(node.arguments[0])) return tagElementTypes[node.arguments[0].value] ?? "HTMLElement";
214
+ return inferElementType(node.callee.object, bindings);
215
+ }
207
216
  if (_babel_types.isIdentifier(node.callee)) {
208
217
  if (node.callee.name === "h" && _babel_types.isStringLiteral(node.arguments[0])) return tagElementTypes[node.arguments[0].value] ?? "HTMLElement";
209
218
  return factoryElementTypes[node.callee.name];
210
219
  }
211
- if (_babel_types.isMemberExpression(node.callee)) {
212
- if (_babel_types.isMemberExpression(node.callee) && _babel_types.isIdentifier(node.callee.property, { name: "createElement" }) && _babel_types.isIdentifier(node.callee.object, { name: "document" }) && _babel_types.isStringLiteral(node.arguments[0])) return tagElementTypes[node.arguments[0].value] ?? "HTMLElement";
213
- return inferElementType(node.callee.object, bindings);
214
- }
215
220
  }
216
221
  }
217
222
  function getElementTypeFromTypeAnnotation(node) {
@@ -234,20 +239,24 @@ function transformElementFile(code, usedMethods, options) {
234
239
  });
235
240
  let modified = false;
236
241
  const prototypeMethods = /* @__PURE__ */ new Map();
242
+ const assignments = [];
237
243
  for (const node of ast.program.body) {
238
- if (!_babel_types.isExpressionStatement(node) || !_babel_types.isCallExpression(node.expression)) continue;
239
- const targetPrototype = getAssignedPrototype(node.expression.arguments[0]);
240
- const sourceArg = unwrapExpression(node.expression.arguments[1]);
241
- if (!targetPrototype || !_babel_types.isObjectExpression(sourceArg)) continue;
242
- prototypeMethods.set(targetPrototype, new Set(sourceArg.properties.map((prop) => _babel_types.isObjectProperty(prop) || _babel_types.isObjectMethod(prop) ? getPropertyName(prop.key) : void 0).filter((methodName) => !!methodName)));
244
+ if (!_babel_types.isExpressionStatement(node)) continue;
245
+ for (const expression of _babel_types.isSequenceExpression(node.expression) ? node.expression.expressions : [node.expression]) {
246
+ if (!_babel_types.isCallExpression(expression) || !_babel_types.isIdentifier(expression.callee, { name: "$_" }) || expression.arguments.length < 2) continue;
247
+ const targetPrototype = getEnhancedPrototype(expression.arguments[0]);
248
+ const sourceArg = unwrapExpression(expression.arguments[1]);
249
+ if (targetPrototype && _babel_types.isObjectExpression(sourceArg)) {
250
+ assignments.push({
251
+ targetPrototype,
252
+ sourceArg,
253
+ call: expression
254
+ });
255
+ prototypeMethods.set(targetPrototype, new Set(sourceArg.properties.map((prop) => _babel_types.isObjectProperty(prop) || _babel_types.isObjectMethod(prop) ? getPropertyName(prop.key) : void 0).filter((methodName) => !!methodName)));
256
+ }
257
+ }
243
258
  }
244
- for (const node of ast.program.body) {
245
- if (!_babel_types.isExpressionStatement(node) || !_babel_types.isCallExpression(node.expression)) continue;
246
- const callExpr = node.expression;
247
- if (!_babel_types.isMemberExpression(callExpr.callee) || !_babel_types.isIdentifier(callExpr.callee.object, { name: "Object" }) || !_babel_types.isIdentifier(callExpr.callee.property, { name: "assign" }) || callExpr.arguments.length < 2) continue;
248
- const targetPrototype = getAssignedPrototype(callExpr.arguments[0]);
249
- const sourceArg = unwrapExpression(callExpr.arguments[1]);
250
- if (!targetPrototype || !_babel_types.isObjectExpression(sourceArg)) continue;
259
+ for (const { targetPrototype, sourceArg } of assignments) {
251
260
  const originalProperties = sourceArg.properties.length;
252
261
  sourceArg.properties = sourceArg.properties.filter((prop) => {
253
262
  if (!_babel_types.isObjectProperty(prop) && !_babel_types.isObjectMethod(prop)) return true;
@@ -261,6 +270,19 @@ function transformElementFile(code, usedMethods, options) {
261
270
  if (options.debug) console.log(`[zed-gpui] Removed ${originalProperties - sourceArg.properties.length} unused methods from ${targetPrototype}`);
262
271
  }
263
272
  }
273
+ ast.program.body = ast.program.body.filter((node) => {
274
+ if (!_babel_types.isExpressionStatement(node)) return true;
275
+ if (_babel_types.isSequenceExpression(node.expression)) {
276
+ const expressions = node.expression.expressions.filter((expression) => !assignments.some(({ call, sourceArg }) => call === expression && sourceArg.properties.length === 0));
277
+ if (expressions.length !== node.expression.expressions.length) modified = true;
278
+ if (expressions.length === 0) return false;
279
+ node.expression = expressions.length === 1 ? expressions[0] : _babel_types.sequenceExpression(expressions);
280
+ return true;
281
+ }
282
+ const shouldRemove = assignments.some(({ call, sourceArg }) => call === node.expression && sourceArg.properties.length === 0);
283
+ if (shouldRemove) modified = true;
284
+ return !shouldRemove;
285
+ });
264
286
  if (modified) return { code: (0, _babel_generator.default)(ast, {}, code).code };
265
287
  return null;
266
288
  } catch (error) {
@@ -268,8 +290,8 @@ function transformElementFile(code, usedMethods, options) {
268
290
  return null;
269
291
  }
270
292
  }
271
- function getAssignedPrototype(node) {
272
- return _babel_types.isMemberExpression(node) && _babel_types.isIdentifier(node.object) && _babel_types.isIdentifier(node.property, { name: "prototype" }) && isElementType(node.object.name) ? node.object.name : void 0;
293
+ function getEnhancedPrototype(node) {
294
+ return _babel_types.isIdentifier(node) && isElementType(node.name) ? node.name : void 0;
273
295
  }
274
296
  function unwrapExpression(node) {
275
297
  while (_babel_types.isTSAsExpression(node) || _babel_types.isTSTypeAssertion(node) || _babel_types.isTSNonNullExpression(node)) node = node.expression;
package/dist/index.d.ts CHANGED
@@ -20,6 +20,6 @@ interface PluginOptions {
20
20
  * Unplugin for zed-gpui tree-shaking optimization
21
21
  * Removes unused zed-gpui methods from the bundle
22
22
  */
23
- declare const zedGpuiPlugin: import("unplugin").UnpluginInstance<PluginOptions, boolean>;
23
+ declare const zedGpuiPlugin: import("unplugin").UnpluginInstance<PluginOptions | undefined, boolean>;
24
24
  //#endregion
25
25
  export { PluginOptions, zedGpuiPlugin as default, zedGpuiPlugin };
package/dist/index.mjs CHANGED
@@ -57,14 +57,14 @@ const zedGpuiPlugin = createUnplugin((options = {}) => {
57
57
  return {
58
58
  name: "unplugin-zed-gpui",
59
59
  transform(code, id) {
60
- if (hasElementPrototypeAssign(code)) {
60
+ if (shouldProcessFile(id)) analyzeUsage(code, usedMethods, opts);
61
+ if (hasPrototypeEnhancement(code)) {
61
62
  if (opts.debug) {
62
63
  console.log(`[zed-gpui] Processing element file: ${id}`);
63
64
  console.log(`[zed-gpui] Used methods:`, formatUsedMethods(usedMethods));
64
65
  }
65
66
  return transformElementFile(code, usedMethods, opts);
66
67
  }
67
- if (shouldProcessFile(id)) analyzeUsage(code, usedMethods, opts);
68
68
  return null;
69
69
  },
70
70
  buildEnd() {
@@ -111,8 +111,8 @@ function analyzeUsage(code, usedMethods, options) {
111
111
  function hasZedGpuiUsage(code) {
112
112
  return /\.\s*([a-z_][a-zA-Z0-9_]*)\s*\(/.test(code);
113
113
  }
114
- function hasElementPrototypeAssign(code) {
115
- return code.includes("Object.assign") && /HTML[A-Za-z]*Element\.prototype/.test(code);
114
+ function hasPrototypeEnhancement(code) {
115
+ return code.includes("$_(") && /HTML[A-Za-z]*Element/.test(code);
116
116
  }
117
117
  /**
118
118
  * Recursively scan AST nodes for method calls
@@ -175,15 +175,20 @@ function addUsedMethod(usedMethods, elementType, methodName) {
175
175
  function inferElementType(node, bindings) {
176
176
  if (t.isIdentifier(node)) return bindings.get(node.name);
177
177
  if (t.isTSAsExpression(node) || t.isTSTypeAssertion(node)) return getElementTypeFromTsType(node.typeAnnotation) ?? inferElementType(node.expression, bindings);
178
+ if (t.isTSNonNullExpression(node)) return inferElementType(node.expression, bindings);
178
179
  if (t.isCallExpression(node)) {
180
+ if (t.isMemberExpression(node.callee)) {
181
+ if (t.isIdentifier(node.callee.object, { name: "document" }) && (t.isIdentifier(node.callee.property, { name: "querySelector" }) || t.isIdentifier(node.callee.property, { name: "getElementById" }))) {
182
+ const typeArg = node.typeArguments?.params[0];
183
+ return typeArg && t.isTSType(typeArg) ? getElementTypeFromTsType(typeArg) : "HTMLElement";
184
+ }
185
+ if (t.isIdentifier(node.callee.property, { name: "createElement" }) && t.isIdentifier(node.callee.object, { name: "document" }) && t.isStringLiteral(node.arguments[0])) return tagElementTypes[node.arguments[0].value] ?? "HTMLElement";
186
+ return inferElementType(node.callee.object, bindings);
187
+ }
179
188
  if (t.isIdentifier(node.callee)) {
180
189
  if (node.callee.name === "h" && t.isStringLiteral(node.arguments[0])) return tagElementTypes[node.arguments[0].value] ?? "HTMLElement";
181
190
  return factoryElementTypes[node.callee.name];
182
191
  }
183
- if (t.isMemberExpression(node.callee)) {
184
- if (t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.property, { name: "createElement" }) && t.isIdentifier(node.callee.object, { name: "document" }) && t.isStringLiteral(node.arguments[0])) return tagElementTypes[node.arguments[0].value] ?? "HTMLElement";
185
- return inferElementType(node.callee.object, bindings);
186
- }
187
192
  }
188
193
  }
189
194
  function getElementTypeFromTypeAnnotation(node) {
@@ -206,20 +211,24 @@ function transformElementFile(code, usedMethods, options) {
206
211
  });
207
212
  let modified = false;
208
213
  const prototypeMethods = /* @__PURE__ */ new Map();
214
+ const assignments = [];
209
215
  for (const node of ast.program.body) {
210
- if (!t.isExpressionStatement(node) || !t.isCallExpression(node.expression)) continue;
211
- const targetPrototype = getAssignedPrototype(node.expression.arguments[0]);
212
- const sourceArg = unwrapExpression(node.expression.arguments[1]);
213
- if (!targetPrototype || !t.isObjectExpression(sourceArg)) continue;
214
- prototypeMethods.set(targetPrototype, new Set(sourceArg.properties.map((prop) => t.isObjectProperty(prop) || t.isObjectMethod(prop) ? getPropertyName(prop.key) : void 0).filter((methodName) => !!methodName)));
216
+ if (!t.isExpressionStatement(node)) continue;
217
+ for (const expression of t.isSequenceExpression(node.expression) ? node.expression.expressions : [node.expression]) {
218
+ if (!t.isCallExpression(expression) || !t.isIdentifier(expression.callee, { name: "$_" }) || expression.arguments.length < 2) continue;
219
+ const targetPrototype = getEnhancedPrototype(expression.arguments[0]);
220
+ const sourceArg = unwrapExpression(expression.arguments[1]);
221
+ if (targetPrototype && t.isObjectExpression(sourceArg)) {
222
+ assignments.push({
223
+ targetPrototype,
224
+ sourceArg,
225
+ call: expression
226
+ });
227
+ prototypeMethods.set(targetPrototype, new Set(sourceArg.properties.map((prop) => t.isObjectProperty(prop) || t.isObjectMethod(prop) ? getPropertyName(prop.key) : void 0).filter((methodName) => !!methodName)));
228
+ }
229
+ }
215
230
  }
216
- for (const node of ast.program.body) {
217
- if (!t.isExpressionStatement(node) || !t.isCallExpression(node.expression)) continue;
218
- const callExpr = node.expression;
219
- if (!t.isMemberExpression(callExpr.callee) || !t.isIdentifier(callExpr.callee.object, { name: "Object" }) || !t.isIdentifier(callExpr.callee.property, { name: "assign" }) || callExpr.arguments.length < 2) continue;
220
- const targetPrototype = getAssignedPrototype(callExpr.arguments[0]);
221
- const sourceArg = unwrapExpression(callExpr.arguments[1]);
222
- if (!targetPrototype || !t.isObjectExpression(sourceArg)) continue;
231
+ for (const { targetPrototype, sourceArg } of assignments) {
223
232
  const originalProperties = sourceArg.properties.length;
224
233
  sourceArg.properties = sourceArg.properties.filter((prop) => {
225
234
  if (!t.isObjectProperty(prop) && !t.isObjectMethod(prop)) return true;
@@ -233,6 +242,19 @@ function transformElementFile(code, usedMethods, options) {
233
242
  if (options.debug) console.log(`[zed-gpui] Removed ${originalProperties - sourceArg.properties.length} unused methods from ${targetPrototype}`);
234
243
  }
235
244
  }
245
+ ast.program.body = ast.program.body.filter((node) => {
246
+ if (!t.isExpressionStatement(node)) return true;
247
+ if (t.isSequenceExpression(node.expression)) {
248
+ const expressions = node.expression.expressions.filter((expression) => !assignments.some(({ call, sourceArg }) => call === expression && sourceArg.properties.length === 0));
249
+ if (expressions.length !== node.expression.expressions.length) modified = true;
250
+ if (expressions.length === 0) return false;
251
+ node.expression = expressions.length === 1 ? expressions[0] : t.sequenceExpression(expressions);
252
+ return true;
253
+ }
254
+ const shouldRemove = assignments.some(({ call, sourceArg }) => call === node.expression && sourceArg.properties.length === 0);
255
+ if (shouldRemove) modified = true;
256
+ return !shouldRemove;
257
+ });
236
258
  if (modified) return { code: generate(ast, {}, code).code };
237
259
  return null;
238
260
  } catch (error) {
@@ -240,8 +262,8 @@ function transformElementFile(code, usedMethods, options) {
240
262
  return null;
241
263
  }
242
264
  }
243
- function getAssignedPrototype(node) {
244
- return t.isMemberExpression(node) && t.isIdentifier(node.object) && t.isIdentifier(node.property, { name: "prototype" }) && isElementType(node.object.name) ? node.object.name : void 0;
265
+ function getEnhancedPrototype(node) {
266
+ return t.isIdentifier(node) && isElementType(node.name) ? node.name : void 0;
245
267
  }
246
268
  function unwrapExpression(node) {
247
269
  while (t.isTSAsExpression(node) || t.isTSTypeAssertion(node) || t.isTSNonNullExpression(node)) node = node.expression;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unplugin-zed-gpui",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Unplugin for zed-gpui tree-shaking optimization - removes unused zed-gpui methods from bundle",
5
5
  "author": {
6
6
  "name": "Kasukabe Tsumugi",