@planningcenter/tapestry-migration-cli 2.4.0-rc.2 → 2.4.0-rc.21

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.
Files changed (42) hide show
  1. package/README.md +100 -6
  2. package/dist/tapestry-react-shim.cjs +1 -1
  3. package/package.json +2 -2
  4. package/src/components/button/index.ts +3 -3
  5. package/src/components/button/transforms/childrenToLabel.test.ts +5 -4
  6. package/src/components/button/transforms/childrenToLabel.ts +9 -39
  7. package/src/components/button/transforms/innerRefToRef.test.ts +170 -0
  8. package/src/components/button/transforms/innerRefToRef.ts +14 -0
  9. package/src/components/button/transforms/unsupportedProps.ts +8 -31
  10. package/src/components/link/index.ts +22 -2
  11. package/src/components/link/transforms/auditSpreadProps.test.ts +351 -0
  12. package/src/components/link/transforms/auditSpreadProps.ts +24 -0
  13. package/src/components/link/transforms/childrenToLabel.test.ts +331 -0
  14. package/src/components/link/transforms/childrenToLabel.ts +54 -0
  15. package/src/components/link/transforms/convertStyleProps.test.ts +391 -0
  16. package/src/components/link/transforms/convertStyleProps.ts +10 -0
  17. package/src/components/link/transforms/innerRefToRef.test.ts +170 -0
  18. package/src/components/link/transforms/innerRefToRef.ts +14 -0
  19. package/src/components/link/transforms/moveLinkImport.test.ts +295 -0
  20. package/src/components/{button/transforms/linkToButton.ts → link/transforms/moveLinkImport.ts} +4 -5
  21. package/src/components/link/transforms/removeAs.test.ts +192 -0
  22. package/src/components/link/transforms/removeAs.ts +17 -0
  23. package/src/components/link/transforms/{inlineToKind.test.ts → removeInlineMember.test.ts} +13 -28
  24. package/src/components/link/transforms/removeInlineMember.ts +11 -0
  25. package/src/components/link/transforms/removeInlineProp.test.ts +295 -0
  26. package/src/components/link/transforms/removeInlineProp.ts +15 -0
  27. package/src/components/link/transforms/reviewStyles.test.ts +172 -0
  28. package/src/components/link/transforms/reviewStyles.ts +17 -0
  29. package/src/components/link/transforms/targetBlankToExternal.test.ts +14 -0
  30. package/src/components/link/transforms/tooltipToWrapper.test.ts +392 -0
  31. package/src/components/link/transforms/tooltipToWrapper.ts +35 -0
  32. package/src/components/link/transforms/unsupportedProps.test.ts +265 -0
  33. package/src/components/link/transforms/unsupportedProps.ts +58 -0
  34. package/src/components/shared/conditions/hasAttributeValue.test.ts +22 -1
  35. package/src/components/shared/conditions/hasAttributeValue.ts +24 -6
  36. package/src/components/shared/helpers/childrenToLabelHelpers.ts +43 -0
  37. package/src/components/shared/helpers/unsupportedPropsHelpers.ts +35 -0
  38. package/src/components/shared/transformFactories/stylePropTransformFactory.ts +5 -1
  39. package/src/index.ts +18 -7
  40. package/src/stubs/textPlugin.ts +45 -0
  41. package/src/components/button/transforms/linkToButton.test.ts +0 -426
  42. package/src/components/link/transforms/inlineToKind.ts +0 -51
@@ -0,0 +1,295 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./moveLinkImport"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string): string | null {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ return transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ {}
14
+ ) as string | null
15
+ }
16
+
17
+ describe("moveLinkImport transform", () => {
18
+ describe("basic transformations", () => {
19
+ it("should move Link import from tapestry-react to tapestry", () => {
20
+ const input = `
21
+ import { Link } from "@planningcenter/tapestry-react"
22
+
23
+ export default function Test() {
24
+ return <Link href="/test">Test</Link>
25
+ }
26
+ `.trim()
27
+
28
+ const expected = `
29
+ import { Link } from "@planningcenter/tapestry";
30
+
31
+ export default function Test() {
32
+ return <Link href="/test">Test</Link>
33
+ }
34
+ `.trim()
35
+
36
+ const result = applyTransform(input)
37
+ expect(result?.trim()).toBe(expected)
38
+ })
39
+
40
+ it("should handle multiple Link components", () => {
41
+ const input = `
42
+ import { Link } from "@planningcenter/tapestry-react"
43
+
44
+ export default function Test() {
45
+ return (
46
+ <div>
47
+ <Link href="/home">Home</Link>
48
+ <Link href="/about">About</Link>
49
+ </div>
50
+ )
51
+ }
52
+ `.trim()
53
+
54
+ const expected = `
55
+ import { Link } from "@planningcenter/tapestry";
56
+
57
+ export default function Test() {
58
+ return (
59
+ <div>
60
+ <Link href="/home">Home</Link>
61
+ <Link href="/about">About</Link>
62
+ </div>
63
+ )
64
+ }
65
+ `.trim()
66
+
67
+ const result = applyTransform(input)
68
+ expect(result?.trim()).toBe(expected)
69
+ })
70
+
71
+ it("should preserve other imports from tapestry-react", () => {
72
+ const input = `
73
+ import { Link, Button, Input } from "@planningcenter/tapestry-react"
74
+
75
+ export default function Test() {
76
+ return <Link href="/test">Test</Link>
77
+ }
78
+ `.trim()
79
+
80
+ const result = applyTransform(input)
81
+ expect(result).toContain(
82
+ 'import { Button, Input } from "@planningcenter/tapestry-react"'
83
+ )
84
+ expect(result).toContain(
85
+ 'import { Link } from "@planningcenter/tapestry"'
86
+ )
87
+ expect(result).toContain('<Link href="/test">Test</Link>')
88
+ expect(result).not.toContain(
89
+ 'Link, Button } from "@planningcenter/tapestry-react"'
90
+ )
91
+ })
92
+ })
93
+
94
+ describe("import conflict handling", () => {
95
+ it("should use alias when Link already imported from tapestry", () => {
96
+ const input = `
97
+ import { Link } from "@planningcenter/tapestry"
98
+ import { Link as ReactLink } from "@planningcenter/tapestry-react"
99
+
100
+ export default function Test() {
101
+ return <ReactLink href="/test">Test</ReactLink>
102
+ }
103
+ `.trim()
104
+
105
+ const result = applyTransform(input)
106
+ expect(result).toContain(
107
+ 'import { Link } from "@planningcenter/tapestry"'
108
+ )
109
+ expect(result).toContain('<Link href="/test">Test</Link>')
110
+ expect(result).not.toContain('from "@planningcenter/tapestry-react"')
111
+ expect(result).not.toContain("ReactLink")
112
+ })
113
+
114
+ it("should handle existing tapestry import with other components", () => {
115
+ const input = `
116
+ import { Button, Input } from "@planningcenter/tapestry"
117
+ import { Link } from "@planningcenter/tapestry-react"
118
+
119
+ export default function Test() {
120
+ return <Link href="/test">Test</Link>
121
+ }
122
+ `.trim()
123
+
124
+ const result = applyTransform(input)
125
+ expect(result).toContain(
126
+ 'import { Button, Input, Link } from "@planningcenter/tapestry"'
127
+ )
128
+ expect(result).toContain('<Link href="/test">Test</Link>')
129
+ expect(result).not.toContain('from "@planningcenter/tapestry-react"')
130
+ })
131
+ })
132
+
133
+ describe("edge cases", () => {
134
+ it("should not transform if Link is not imported from tapestry-react", () => {
135
+ const input = `
136
+ import { Button } from "@planningcenter/tapestry-react"
137
+
138
+ export default function Test() {
139
+ return <Button>Test</Button>
140
+ }
141
+ `.trim()
142
+
143
+ const result = applyTransform(input)
144
+ expect(result).toBe(null)
145
+ })
146
+
147
+ it("should handle Link with aliased import", () => {
148
+ const input = `
149
+ import { Link as ReactLink } from "@planningcenter/tapestry-react"
150
+
151
+ export default function Test() {
152
+ return <ReactLink href="/test">Test</ReactLink>
153
+ }
154
+ `.trim()
155
+
156
+ const result = applyTransform(input)
157
+ expect(result).toContain(
158
+ 'import { Link } from "@planningcenter/tapestry"'
159
+ )
160
+ expect(result).toContain('<Link href="/test">Test</Link>')
161
+ expect(result).not.toContain("ReactLink")
162
+ expect(result).not.toContain('from "@planningcenter/tapestry-react"')
163
+ })
164
+
165
+ it("should handle self-closing Link components", () => {
166
+ const input = `
167
+ import { Link } from "@planningcenter/tapestry-react"
168
+
169
+ export default function Test() {
170
+ return <Link href="/test" />
171
+ }
172
+ `.trim()
173
+
174
+ const expected = `
175
+ import { Link } from "@planningcenter/tapestry";
176
+
177
+ export default function Test() {
178
+ return <Link href="/test" />
179
+ }
180
+ `.trim()
181
+
182
+ const result = applyTransform(input)
183
+ expect(result?.trim()).toBe(expected)
184
+ })
185
+
186
+ it("should handle Link with props", () => {
187
+ const input = `
188
+ import { Link } from "@planningcenter/tapestry-react"
189
+
190
+ export default function Test() {
191
+ return <Link href="/test" kind="primary" onClick={handleClick}>Test</Link>
192
+ }
193
+ `.trim()
194
+
195
+ const result = applyTransform(input)
196
+ expect(result).toContain(
197
+ 'import { Link } from "@planningcenter/tapestry"'
198
+ )
199
+ expect(result).toContain('kind="primary"')
200
+ expect(result).toContain("onClick={handleClick}")
201
+ expect(result).not.toContain('from "@planningcenter/tapestry-react"')
202
+ })
203
+ })
204
+
205
+ describe("no changes scenarios", () => {
206
+ it("should return null when no Link import exists", () => {
207
+ const input = `
208
+ import React from "react"
209
+
210
+ export default function Test() {
211
+ return <div>Hello</div>
212
+ }
213
+ `.trim()
214
+
215
+ const result = applyTransform(input)
216
+ expect(result).toBe(null)
217
+ })
218
+
219
+ it("should return null when Link already imported from tapestry", () => {
220
+ const input = `
221
+ import { Link } from "@planningcenter/tapestry"
222
+
223
+ export default function Test() {
224
+ return <Link href="/test">Test</Link>
225
+ }
226
+ `.trim()
227
+
228
+ const result = applyTransform(input)
229
+ expect(result).toBe(null)
230
+ })
231
+
232
+ it("should return null for empty file", () => {
233
+ const result = applyTransform("")
234
+ expect(result).toBe(null)
235
+ })
236
+ })
237
+
238
+ describe("complex scenarios", () => {
239
+ it("should handle mixed imports and multiple components", () => {
240
+ const input = `
241
+ import React from "react"
242
+ import { Link, Button } from "@planningcenter/tapestry-react"
243
+ import { Input } from "@planningcenter/tapestry"
244
+
245
+ export default function Test() {
246
+ return (
247
+ <form>
248
+ <Input name="email" />
249
+ <Button type="submit">Submit</Button>
250
+ <Link href="/cancel">Cancel</Link>
251
+ </form>
252
+ )
253
+ }
254
+ `.trim()
255
+
256
+ const result = applyTransform(input)
257
+ expect(result).toContain(
258
+ 'import { Button } from "@planningcenter/tapestry-react"'
259
+ )
260
+ expect(result).toContain(
261
+ 'import { Input, Link } from "@planningcenter/tapestry"'
262
+ )
263
+ expect(result).toContain('<Button type="submit">Submit</Button>')
264
+ expect(result).toContain('<Link href="/cancel">Cancel</Link>')
265
+ expect(result).not.toContain(
266
+ 'Link, Button } from "@planningcenter/tapestry-react"'
267
+ )
268
+ })
269
+
270
+ it("should handle Link usage in JSX expressions", () => {
271
+ const input = `
272
+ import { Link } from "@planningcenter/tapestry-react"
273
+
274
+ export default function Test({ showLink }) {
275
+ return (
276
+ <div>
277
+ {showLink && <Link href="/conditional">Conditional</Link>}
278
+ {items.map(item => <Link key={item.id} href={item.url}>{item.name}</Link>)}
279
+ </div>
280
+ )
281
+ }
282
+ `.trim()
283
+
284
+ const result = applyTransform(input)
285
+ expect(result).toContain(
286
+ 'import { Link } from "@planningcenter/tapestry"'
287
+ )
288
+ expect(result).toContain('<Link href="/conditional">Conditional</Link>')
289
+ expect(result).toContain(
290
+ "<Link key={item.id} href={item.url}>{item.name}</Link>"
291
+ )
292
+ expect(result).not.toContain('from "@planningcenter/tapestry-react"')
293
+ })
294
+ })
295
+ })
@@ -1,15 +1,14 @@
1
1
  import { Transform } from "jscodeshift"
2
2
 
3
- import { hasAttribute } from "../../shared/conditions/hasAttribute"
4
3
  import { componentTransformFactory } from "../../shared/transformFactories/componentTransformFactory"
5
4
 
6
5
  const transform: Transform = componentTransformFactory({
7
- condition: hasAttribute("onClick"),
8
- conflictAlias: "TRButton",
6
+ condition: () => true,
7
+ conflictAlias: "TLink",
9
8
  fromComponent: "Link",
10
9
  fromPackage: "@planningcenter/tapestry-react",
11
- toComponent: "Button",
12
- toPackage: "@planningcenter/tapestry-react",
10
+ toComponent: "Link",
11
+ toPackage: "@planningcenter/tapestry",
13
12
  })
14
13
 
15
14
  export default transform
@@ -0,0 +1,192 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import removeAs from "./removeAs"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string): string | null {
9
+ return removeAs(
10
+ { path: "test.tsx", source },
11
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
12
+ {}
13
+ ) as string | null
14
+ }
15
+
16
+ describe("removeAs transform", () => {
17
+ describe("basic transformations", () => {
18
+ it("should remove as='a' attribute from Link", () => {
19
+ const input = `
20
+ import { Link } from "@planningcenter/tapestry-react"
21
+
22
+ export default function Test() {
23
+ return <Link href="/home" as="a">Home</Link>
24
+ }
25
+ `.trim()
26
+
27
+ const expected = `
28
+ import { Link } from "@planningcenter/tapestry-react"
29
+
30
+ export default function Test() {
31
+ return <Link href="/home">Home</Link>;
32
+ }
33
+ `.trim()
34
+
35
+ const result = applyTransform(input)
36
+ expect(result?.trim()).toBe(expected)
37
+ })
38
+
39
+ it("should only remove as='a' attribute, not other as values", () => {
40
+ const input = `
41
+ import { Link } from "@planningcenter/tapestry-react"
42
+
43
+ export default function Test() {
44
+ return (
45
+ <div>
46
+ <Link href="/home" as="a">Home</Link>
47
+ <Link href="/button" as="button">Button</Link>
48
+ </div>
49
+ )
50
+ }
51
+ `.trim()
52
+
53
+ const result = applyTransform(input)
54
+ expect(result).toContain('href="/home"') // Should remain
55
+ expect(result).not.toContain('as="a"') // Should be removed
56
+ expect(result).toContain('as="button"') // Should remain
57
+ })
58
+
59
+ it("should preserve other attributes while removing as='a'", () => {
60
+ const input = `
61
+ import { Link } from "@planningcenter/tapestry-react"
62
+
63
+ export default function Test() {
64
+ return (
65
+ <Link
66
+ href="/external"
67
+ as="a"
68
+ className="nav-link"
69
+ target="_blank"
70
+ rel="noopener"
71
+ >
72
+ External Link
73
+ </Link>
74
+ )
75
+ }
76
+ `.trim()
77
+
78
+ const result = applyTransform(input)
79
+ expect(result).toContain('href="/external"')
80
+ expect(result).toContain('className="nav-link"')
81
+ expect(result).toContain('target="_blank"')
82
+ expect(result).toContain('rel="noopener"')
83
+ expect(result).not.toContain('as="a"')
84
+ })
85
+
86
+ it("should handle Links without as attribute", () => {
87
+ const input = `
88
+ import { Link } from "@planningcenter/tapestry-react"
89
+
90
+ export default function Test() {
91
+ return <Link href="/internal">Internal Link</Link>
92
+ }
93
+ `.trim()
94
+
95
+ const result = applyTransform(input)
96
+ expect(result).toBeNull() // No changes should be made
97
+ })
98
+
99
+ it("should handle Links with as attribute but different value", () => {
100
+ const input = `
101
+ import { Link } from "@planningcenter/tapestry-react"
102
+
103
+ export default function Test() {
104
+ return <Link href="/button" as="button">Button Link</Link>
105
+ }
106
+ `.trim()
107
+
108
+ const result = applyTransform(input)
109
+ expect(result).toBeNull() // No changes should be made
110
+ })
111
+ })
112
+
113
+ describe("edge cases", () => {
114
+ it("should handle multiple Link components", () => {
115
+ const input = `
116
+ import { Link } from "@planningcenter/tapestry-react"
117
+
118
+ export default function Test() {
119
+ return (
120
+ <div>
121
+ <Link href="/page1" as="a">Page 1</Link>
122
+ <Link href="/page2" as="a">Page 2</Link>
123
+ <Link href="/page3">Page 3</Link>
124
+ </div>
125
+ )
126
+ }
127
+ `.trim()
128
+
129
+ const result = applyTransform(input)
130
+ expect(result).not.toContain('as="a"') // Should be removed from both
131
+ expect(result).toContain('href="/page1"')
132
+ expect(result).toContain('href="/page2"')
133
+ expect(result).toContain('href="/page3"') // Should remain unchanged
134
+ })
135
+
136
+ it("should handle self-closing Link components", () => {
137
+ const input = `
138
+ import { Link } from "@planningcenter/tapestry-react"
139
+
140
+ export default function Test() {
141
+ return <Link href="/external" as="a" />
142
+ }
143
+ `.trim()
144
+
145
+ const result = applyTransform(input)
146
+ expect(result).toContain('href="/external"')
147
+ expect(result).not.toContain('as="a"')
148
+ })
149
+
150
+ it("should handle dynamic as values", () => {
151
+ const input = `
152
+ import { Link } from "@planningcenter/tapestry-react"
153
+
154
+ export default function Test() {
155
+ return <Link href="/external" as={isExternal ? "a" : "button"}>Link</Link>
156
+ }
157
+ `.trim()
158
+
159
+ const result = applyTransform(input)
160
+ expect(result).toBeNull() // No changes should be made for dynamic values
161
+ })
162
+ })
163
+
164
+ describe("import handling", () => {
165
+ it("should only transform when Link is imported from correct package", () => {
166
+ const input = `
167
+ import { Link } from "react-router-dom"
168
+
169
+ export default function Test() {
170
+ return <Link to="/external" as="a">External Link</Link>
171
+ }
172
+ `.trim()
173
+
174
+ const result = applyTransform(input)
175
+ expect(result).toBeNull() // No changes should be made
176
+ })
177
+
178
+ it("should handle aliased imports", () => {
179
+ const input = `
180
+ import { Link as TapestryLink } from "@planningcenter/tapestry-react"
181
+
182
+ export default function Test() {
183
+ return <TapestryLink href="/external" as="a">External Link</TapestryLink>
184
+ }
185
+ `.trim()
186
+
187
+ const result = applyTransform(input)
188
+ expect(result).toContain('href="/external"')
189
+ expect(result).not.toContain('as="a"')
190
+ })
191
+ })
192
+ })
@@ -0,0 +1,17 @@
1
+ import { removeAttribute } from "../../shared/actions/removeAttribute"
2
+ import { hasAttributeValue } from "../../shared/conditions/hasAttributeValue"
3
+ import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
4
+
5
+ const transform = attributeTransformFactory({
6
+ condition: hasAttributeValue("as", "a"),
7
+ targetComponent: "Link",
8
+ targetPackage: "@planningcenter/tapestry-react",
9
+ transform: (element, { j, source }) => {
10
+ // Remove as attribute
11
+ removeAttribute("as", { element, j, source })
12
+
13
+ return true
14
+ },
15
+ })
16
+
17
+ export default transform
@@ -1,7 +1,7 @@
1
1
  import jscodeshift from "jscodeshift"
2
2
  import { describe, expect, it } from "vitest"
3
3
 
4
- import transform from "./inlineToKind"
4
+ import transform from "./removeInlineMember"
5
5
 
6
6
  const j = jscodeshift.withParser("tsx")
7
7
 
@@ -14,9 +14,9 @@ function applyTransform(source: string): string | null {
14
14
  ) as string | null
15
15
  }
16
16
 
17
- describe("inlineToKind transform", () => {
17
+ describe("removeInlineMember transform", () => {
18
18
  describe("basic transformations", () => {
19
- it("should transform Link.Inline to Link with kind='inline-text'", () => {
19
+ it("should transform Link.Inline to Link", () => {
20
20
  const input = `
21
21
  import { Link } from "@planningcenter/tapestry-react"
22
22
 
@@ -29,7 +29,7 @@ export default function Test() {
29
29
  import { Link } from "@planningcenter/tapestry-react"
30
30
 
31
31
  export default function Test() {
32
- return <Link href="/profile" kind="inline-text">Profile</Link>;
32
+ return <Link href="/profile">Profile</Link>;
33
33
  }
34
34
  `.trim()
35
35
 
@@ -57,13 +57,11 @@ export default function Test() {
57
57
  `.trim()
58
58
 
59
59
  const result = applyTransform(input)
60
- expect(result).toContain('kind="inline-text"')
61
60
  expect(result).toContain('href="/dashboard"')
62
61
  expect(result).toContain('className="nav-link"')
63
62
  expect(result).toContain('target="_blank"')
64
63
  expect(result).toContain('rel="noopener"')
65
64
  expect(result).toContain('data-testid="profile-link"')
66
- expect(result).toContain('kind="inline-text"')
67
65
  expect(result).toContain("<Link")
68
66
  expect(result).not.toContain("Link.Inline")
69
67
  })
@@ -81,7 +79,7 @@ export default function Test() {
81
79
  import { Link } from "@planningcenter/tapestry-react"
82
80
 
83
81
  export default function Test() {
84
- return <Link href="/dashboard" kind="inline-text" />;
82
+ return <Link href="/dashboard" />;
85
83
  }
86
84
  `.trim()
87
85
 
@@ -104,12 +102,8 @@ export default function Test() {
104
102
  `.trim()
105
103
 
106
104
  const result = applyTransform(input)
107
- expect(result).toContain(
108
- '<Link href="/home" kind="inline-text">Home</Link>'
109
- )
110
- expect(result).toContain(
111
- '<Link href="/about" kind="inline-text">About</Link>'
112
- )
105
+ expect(result).toContain('<Link href="/home">Home</Link>')
106
+ expect(result).toContain('<Link href="/about">About</Link>')
113
107
  expect(result).not.toContain("Link.Inline")
114
108
  })
115
109
  })
@@ -132,9 +126,7 @@ export default function Test() {
132
126
 
133
127
  const result = applyTransform(input)
134
128
  expect(result).toContain('<Link href="/home">Home</Link>')
135
- expect(result).toContain(
136
- '<Link href="/profile" kind="inline-text">Profile</Link>'
137
- )
129
+ expect(result).toContain('<Link href="/profile">Profile</Link>')
138
130
  expect(result).toContain(
139
131
  '<Link as="button" href="/dashboard">Dashboard</Link>'
140
132
  )
@@ -152,7 +144,7 @@ export default function Test() {
152
144
 
153
145
  const result = applyTransform(input)
154
146
  expect(result).toContain(
155
- '<TapestryLink href="/profile" kind="inline-text">Profile</TapestryLink>'
147
+ '<TapestryLink href="/profile">Profile</TapestryLink>'
156
148
  )
157
149
  expect(result).not.toContain("TapestryLink.Inline")
158
150
  })
@@ -175,11 +167,9 @@ export default function Test({ items, showInline }) {
175
167
 
176
168
  const result = applyTransform(input)
177
169
  expect(result).toContain(
178
- '<Link key={item.id} href={item.url} kind="inline-text">{item.name}</Link>'
179
- )
180
- expect(result).toContain(
181
- '<Link href="/conditional" kind="inline-text">Conditional</Link>'
170
+ "<Link key={item.id} href={item.url}>{item.name}</Link>"
182
171
  )
172
+ expect(result).toContain('<Link href="/conditional">Conditional</Link>')
183
173
  expect(result).not.toContain("Link.Inline")
184
174
  })
185
175
  })
@@ -216,7 +206,6 @@ export default function Test({ url, isExternal }) {
216
206
  `.trim()
217
207
 
218
208
  const result = applyTransform(input)
219
- expect(result).toContain('kind="inline-text"')
220
209
  expect(result).toContain("<Link")
221
210
  expect(result).toContain("href={url}")
222
211
  expect(result).toContain('target={isExternal ? "_blank" : "_self"}')
@@ -245,12 +234,8 @@ export default function Test() {
245
234
  `.trim()
246
235
 
247
236
  const result = applyTransform(input)
248
- expect(result).toContain(
249
- '<Link href="/about" kind="inline-text">about page</Link>'
250
- )
251
- expect(result).toContain(
252
- '<Link href="/help" kind="inline-text">help section</Link>'
253
- )
237
+ expect(result).toContain('<Link href="/about">about page</Link>')
238
+ expect(result).toContain('<Link href="/help">help section</Link>')
254
239
  expect(result).not.toContain("Link.Inline")
255
240
  })
256
241
  })
@@ -0,0 +1,11 @@
1
+ import { componentTransformFactory } from "../../shared/transformFactories/componentTransformFactory"
2
+
3
+ const transform = componentTransformFactory({
4
+ condition: () => true, // Transform all Link.Inline elements
5
+ fromComponent: "Link.Inline",
6
+ fromPackage: "@planningcenter/tapestry-react",
7
+ toComponent: "Link",
8
+ toPackage: "@planningcenter/tapestry-react",
9
+ })
10
+
11
+ export default transform