@lego-build/plugins 0.0.10 → 0.0.12

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/auto.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  initIframeBridge
3
- } from "./chunk-FJKEG5SO.js";
3
+ } from "./chunk-2OBTKO4Q.js";
4
4
 
5
5
  // src/auto.ts
6
6
  initIframeBridge();
@@ -8,8 +8,11 @@ interface SourceLocatorPluginOptions {
8
8
  exclude?: string[];
9
9
  }
10
10
  /**
11
- * Babel plugin that adds data-locator-path and data-locator-line attributes
12
- * to JSX elements for inline editing support.
11
+ * Babel plugin that adds data-locator-path, data-locator-line, and data-locator-static
12
+ * attributes to JSX elements for inline editing support.
13
+ *
14
+ * data-locator-static indicates whether the element's text content is purely static
15
+ * (can be safely edited inline) or contains dynamic expressions (editing may fail).
13
16
  */
14
17
  declare function sourceLocatorBabelPlugin({ types }: {
15
18
  types: typeof types;
@@ -1,11 +1,63 @@
1
1
  // src/babel-plugin.ts
2
2
  import * as path from "path";
3
+ function hasOnlyStaticTextContent(types, element) {
4
+ const children = element.node.children;
5
+ for (const child of children) {
6
+ if (types.isJSXText(child)) {
7
+ continue;
8
+ }
9
+ if (types.isJSXExpressionContainer(child)) {
10
+ if (types.isJSXEmptyExpression(child.expression)) {
11
+ continue;
12
+ }
13
+ if (types.isStringLiteral(child.expression) || types.isNumericLiteral(child.expression)) {
14
+ continue;
15
+ }
16
+ if (types.isTemplateLiteral(child.expression) && child.expression.expressions.length === 0) {
17
+ continue;
18
+ }
19
+ return false;
20
+ }
21
+ if (types.isJSXElement(child) || types.isJSXFragment(child)) {
22
+ continue;
23
+ }
24
+ if (types.isJSXSpreadChild(child)) {
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ }
30
+ function extractStaticText(types, element) {
31
+ const children = element.node.children;
32
+ let text = "";
33
+ for (const child of children) {
34
+ if (types.isJSXText(child)) {
35
+ text += child.value;
36
+ } else if (types.isJSXExpressionContainer(child)) {
37
+ if (types.isStringLiteral(child.expression)) {
38
+ text += child.expression.value;
39
+ } else if (types.isNumericLiteral(child.expression)) {
40
+ text += String(child.expression.value);
41
+ } else if (types.isTemplateLiteral(child.expression) && child.expression.expressions.length === 0) {
42
+ text += child.expression.quasis.map((q) => q.value.cooked || q.value.raw).join("");
43
+ } else if (!types.isJSXEmptyExpression(child.expression)) {
44
+ return null;
45
+ }
46
+ } else if (types.isJSXElement(child) || types.isJSXFragment(child)) {
47
+ continue;
48
+ } else {
49
+ return null;
50
+ }
51
+ }
52
+ return text.trim() || null;
53
+ }
3
54
  function sourceLocatorBabelPlugin({ types }, options = {}) {
4
55
  const { exclude = ["node_modules"] } = options;
5
56
  return {
6
57
  name: "lego-source-locator",
7
58
  visitor: {
8
- JSXOpeningElement(nodePath, state) {
59
+ JSXElement(nodePath, state) {
60
+ const openingElement = nodePath.node.openingElement;
9
61
  const filename = state.filename || "";
10
62
  for (const pattern of exclude) {
11
63
  if (filename.includes(pattern)) {
@@ -14,25 +66,41 @@ function sourceLocatorBabelPlugin({ types }, options = {}) {
14
66
  }
15
67
  const cwd = state.cwd || process.cwd();
16
68
  const relativePath = path.relative(cwd, filename);
17
- const hasLocatorPath = nodePath.node.attributes.some(
69
+ const hasLocatorPath = openingElement.attributes.some(
18
70
  (attr) => types.isJSXAttribute(attr) && types.isJSXIdentifier(attr.name) && attr.name.name === "data-locator-path"
19
71
  );
20
72
  if (hasLocatorPath) {
21
73
  return;
22
74
  }
23
- const line = nodePath.node.loc?.start.line || 0;
24
- nodePath.node.attributes.push(
75
+ const line = openingElement.loc?.start.line || 0;
76
+ const isStatic = hasOnlyStaticTextContent(types, nodePath);
77
+ const staticText = isStatic ? extractStaticText(types, nodePath) : null;
78
+ openingElement.attributes.push(
25
79
  types.jsxAttribute(
26
80
  types.jsxIdentifier("data-locator-path"),
27
81
  types.stringLiteral(relativePath)
28
82
  )
29
83
  );
30
- nodePath.node.attributes.push(
84
+ openingElement.attributes.push(
31
85
  types.jsxAttribute(
32
86
  types.jsxIdentifier("data-locator-line"),
33
87
  types.stringLiteral(String(line))
34
88
  )
35
89
  );
90
+ openingElement.attributes.push(
91
+ types.jsxAttribute(
92
+ types.jsxIdentifier("data-locator-static"),
93
+ types.stringLiteral(isStatic ? "true" : "false")
94
+ )
95
+ );
96
+ if (staticText) {
97
+ openingElement.attributes.push(
98
+ types.jsxAttribute(
99
+ types.jsxIdentifier("data-locator-text"),
100
+ types.stringLiteral(staticText)
101
+ )
102
+ );
103
+ }
36
104
  }
37
105
  }
38
106
  };