vite-plugin-vue-forward-slots 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 +78 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +31 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# vite-plugin-vue-forward-slots
|
|
2
|
+
|
|
3
|
+
A tiny Vite plugin that transforms `<ForwardSlots />` into native Vue slot-forwarding template syntax.
|
|
4
|
+
|
|
5
|
+
## Why this exists
|
|
6
|
+
|
|
7
|
+
There are many `ForwardSlots` component implementations, but in real projects we kept hitting reactivity and edge-case issues that were hard to fully solve in a runtime component.
|
|
8
|
+
|
|
9
|
+
This plugin avoids that class of problems by compiling `ForwardSlots` usage directly into native Vue template syntax at build time.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun install vite-plugin-vue-forward-slots
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
// vite.config.ts
|
|
21
|
+
import { defineConfig } from 'vite'
|
|
22
|
+
import vue from '@vitejs/plugin-vue'
|
|
23
|
+
import forwardSlotsPlugin from 'vite-plugin-vue-forward-slots'
|
|
24
|
+
|
|
25
|
+
export default defineConfig({
|
|
26
|
+
plugins: [forwardSlotsPlugin(), vue()],
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Supported syntax
|
|
31
|
+
|
|
32
|
+
Both forms are supported:
|
|
33
|
+
|
|
34
|
+
```vue
|
|
35
|
+
<ForwardSlots />
|
|
36
|
+
<forward-slots></forward-slots>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
You can also forward from a custom slots object:
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<ForwardSlots :slots="resolvedSlots" />
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Transform example
|
|
46
|
+
|
|
47
|
+
Input:
|
|
48
|
+
|
|
49
|
+
```vue
|
|
50
|
+
<template>
|
|
51
|
+
<ForwardSlots :slots="resolvedSlots" />
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Output:
|
|
56
|
+
|
|
57
|
+
```vue
|
|
58
|
+
<template>
|
|
59
|
+
<template v-for="(slot,_idx) in Object.keys(resolvedSlots)" :key="_idx" v-slot:[slot]="slotProps">
|
|
60
|
+
<slot :name="slot" v-bind="slotProps"></slot>
|
|
61
|
+
</template>
|
|
62
|
+
</template>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Development
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
bun install
|
|
69
|
+
bun test
|
|
70
|
+
bun run build
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Publish checklist
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
bun test
|
|
77
|
+
bun run build
|
|
78
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare module '@vue/runtime-core' {
|
|
2
|
+
interface GlobalComponents {
|
|
3
|
+
ForwardSlots: DefineComponent<{
|
|
4
|
+
slots: Record<string, unknown>;
|
|
5
|
+
}>;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export default function forwardSlotsPlugin(): {
|
|
9
|
+
name: string;
|
|
10
|
+
enforce: string;
|
|
11
|
+
transform(code: string, id: string): string | undefined;
|
|
12
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { parse as parseSFC } from '@vue/compiler-sfc';
|
|
2
|
+
const FORWARD_SLOTS_TAG_RE = /<\s*forward-?slots\b([^>]*)\s*(?:\/>|>\s*<\/\s*forward-?slots\s*>)/gi;
|
|
3
|
+
function getSlotsExpression(attributes) {
|
|
4
|
+
const match = attributes.match(/(?:^|\s):slots\s*=\s*(?:"([^"]+)"|'([^']+)')/);
|
|
5
|
+
return match?.[1] || match?.[2] || '$slots';
|
|
6
|
+
}
|
|
7
|
+
export default function forwardSlotsPlugin() {
|
|
8
|
+
return {
|
|
9
|
+
name: 'vite-plugin-vue-forward-slots',
|
|
10
|
+
enforce: 'pre',
|
|
11
|
+
transform(code, id) {
|
|
12
|
+
if (!id.endsWith('.vue'))
|
|
13
|
+
return;
|
|
14
|
+
const { descriptor } = parseSFC(code);
|
|
15
|
+
if (!descriptor.template)
|
|
16
|
+
return;
|
|
17
|
+
const template = descriptor.template.content;
|
|
18
|
+
const replaced = template.replace(FORWARD_SLOTS_TAG_RE, (_, attributes) => {
|
|
19
|
+
const expr = getSlotsExpression(attributes || '');
|
|
20
|
+
return `
|
|
21
|
+
<template v-for="(slot,_idx) in Object.keys(${expr})" :key="_idx" v-slot:[slot]="slotProps">
|
|
22
|
+
<slot :name="slot" v-bind="slotProps"></slot>
|
|
23
|
+
</template>
|
|
24
|
+
`;
|
|
25
|
+
});
|
|
26
|
+
if (replaced === template)
|
|
27
|
+
return;
|
|
28
|
+
return code.replace(template, replaced);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vite-plugin-vue-forward-slots",
|
|
3
|
+
"author": "Genesis Studio LLC <studio@gnz.is> (https://studio.gnz.is)",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/021-projects/vite-plugin-vue-forward-slots.git"
|
|
7
|
+
},
|
|
8
|
+
"version": "0.1.0",
|
|
9
|
+
"description": "Vite plugin that compiles <ForwardSlots> into native Vue slot forwarding syntax.",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"module": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc -p tsconfig.build.json",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"prepublishOnly": "bun run build && bun run test"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@vue/compiler-dom": "^3.5.31",
|
|
33
|
+
"@vue/compiler-sfc": "^3.5.31",
|
|
34
|
+
"typescript": "^5.8.3",
|
|
35
|
+
"vitest": "^3.2.4"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"vite": "^5 || ^6 || ^7",
|
|
39
|
+
"vue": "^3.3.0"
|
|
40
|
+
},
|
|
41
|
+
"funding": [
|
|
42
|
+
{
|
|
43
|
+
"type": "individual",
|
|
44
|
+
"url": "https://btcpay.gnz.is/apps/2iTijXXYdXMZstbGV8RtdXceWDEc/crowdfund"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|