Skip to content

Commit eb1dd9b

Browse files
fix: moves provider inside root node if possible. (formkit/formkit#1095)
1 parent 690b9ed commit eb1dd9b

File tree

3 files changed

+63
-15
lines changed

3 files changed

+63
-15
lines changed

src/index.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,25 @@ function getRootBlock(
1010
root: RootNode,
1111
block: 'template' | 'script' | 'style',
1212
): ElementNode | undefined {
13-
return root.children.find((node) => node.type === 1 && node.tag === block) as
14-
| ElementNode
15-
| undefined
13+
const node = root.children.find(
14+
(node) => node.type === 1 && node.tag === block,
15+
) as ElementNode | undefined
16+
if (node && block === 'template' && node.children.length === 1) {
17+
const rootChild = node.children[0].type === 1 ? node.children[0] : undefined
18+
const tag = (rootChild?.tag ?? '').toLocaleLowerCase()
19+
if (
20+
rootChild &&
21+
tag !== 'formkit' &&
22+
tag !== 'form-kit' &&
23+
rootChild.isSelfClosing === false
24+
) {
25+
// In this case the component has a root node that is not formkit and is
26+
// not self-closing, like, perhaps, a div. We need to move the provider
27+
// inside this div instead of outside it.
28+
return rootChild
29+
}
30+
}
31+
return node
1632
}
1733

1834
/**
@@ -157,7 +173,7 @@ export const unpluginFactory: UnpluginFactory<Options | undefined> = (
157173
},
158174
// webpack's id filter is outside of loader logic,
159175
// an additional hook is needed for better perf on webpack
160-
transformInclude(id: string) {
176+
transformInclude(_id: string) {
161177
// TODO: resolve why @formkit/vue is not always identifiable by the id
162178
// and remove this early return workaround:
163179
return true

test/__snapshots__/index.test.ts.snap

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ import { FormKit } from '@formkit/vue'
1717
</template>"
1818
`;
1919

20+
exports[`index > injects inside root node if there is one 1`] = `
21+
"<script setup>import { FormKitLazyProvider } from '@formkit/vue'</script>
22+
<template>
23+
<div>
24+
25+
<FormKitLazyProvider> <FormKit /></FormKitLazyProvider>
26+
27+
</div>
28+
</template>"
29+
`;
30+
2031
exports[`index > injects setup block when using options api 1`] = `
2132
"<script setup lang=\\"ts\\">import { FormKitLazyProvider } from '@formkit/vue'</script>
2233
<script lang=\\"ts\\">
@@ -30,12 +41,12 @@ export default {
3041
</script>
3142
3243
<template>
33-
<FormKitLazyProvider>
3444
<div>
35-
<h1>Nothing to see here</h1>
36-
<FormKit type=\\"text\\" label=\\"Check me out\\" />
45+
46+
<FormKitLazyProvider><h1>Nothing to see here</h1>
47+
<FormKit type=\\"text\\" label=\\"Check me out\\" </FormKitLazyProvider>
48+
/>
3749
</div>
38-
</FormKitLazyProvider>
3950
</template>"
4051
`;
4152

test/index.test.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { describe, expect, it } from 'vitest'
22
import unplugin from '../src/vite'
33
import { readFileSync } from 'fs'
44

5-
type Transformer = { transform: (code: string, id: string) => Promise<string> }
5+
type Transformer = {
6+
transform: (code: string, id: string) => Promise<{ code: string; map?: any }>
7+
}
68
const aboutSFCFile = readFileSync('./playground/src/pages/about.vue', 'utf-8')
79
const contactSFCFile = readFileSync(
810
'./playground/src/pages/contact.vue',
@@ -14,22 +16,41 @@ const plugin: Transformer = unplugin() as Transformer
1416
describe('index', () => {
1517
it('injects the template block into an normally structured sfc', async () => {
1618
expect(
17-
await plugin.transform(
18-
`<template>
19+
(
20+
await plugin.transform(
21+
`<template>
1922
<FormKit />
2023
</template>`,
21-
'test.vue',
22-
),
24+
'test.vue',
25+
)
26+
).code,
27+
).toMatchSnapshot()
28+
})
29+
30+
it('injects inside root node if there is one', async () => {
31+
expect(
32+
(
33+
await plugin.transform(
34+
`<template>
35+
<div>
36+
<FormKit />
37+
</div>
38+
</template>`,
39+
'test.vue',
40+
)
41+
).code,
2342
).toMatchSnapshot()
2443
})
2544

2645
it('injects import into script setup block', async () => {
27-
expect(await plugin.transform(aboutSFCFile, 'about.vue')).toMatchSnapshot()
46+
expect(
47+
(await plugin.transform(aboutSFCFile, 'about.vue')).code,
48+
).toMatchSnapshot()
2849
})
2950

3051
it('injects setup block when using options api', async () => {
3152
expect(
32-
await plugin.transform(contactSFCFile, 'about.vue'),
53+
(await plugin.transform(contactSFCFile, 'about.vue')).code,
3354
).toMatchSnapshot()
3455
})
3556
})

0 commit comments

Comments
 (0)