1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
import type { AstroIntegration } from 'astro';
import type { Plugin } from 'vite';
import { resolve } from 'node:path';
interface Options {
/**
* You can extend Alpine by setting this option to a root-relative import specifier (for example, `entrypoint: "/src/entrypoint"`).
*
* The default export of this file should be a function that accepts an Alpine instance prior to starting, allowing the use of custom directives, plugins and other customizations for advanced use cases.
*
* ```js
* // astro.config.mjs
* import { defineConfig } from 'astro/config';
* import alpine from '@astrojs/alpinejs';
*
* export default defineConfig({
* // ...
* integrations: [alpine({ entrypoint: '/src/entrypoint' })],
* });
* ```
*
* ```js
* // src/entrypoint.ts
* import type { Alpine } from 'alpinejs'
*
* export default (Alpine: Alpine) => {
* Alpine.directive('foo', el => {
* el.textContent = 'bar';
* })
* }
* ```
*/
entrypoint?: string;
}
function virtualEntrypoint(options?: Options): Plugin {
const virtualModuleId = 'virtual:@astrojs/alpinejs/entrypoint';
const resolvedVirtualModuleId = '\0' + virtualModuleId;
let isBuild: boolean;
let root: string;
let entrypoint: string | undefined;
return {
name: '@astrojs/alpinejs/virtual-entrypoint',
config(_, { command }) {
isBuild = command === 'build';
},
configResolved(config) {
root = config.root;
if (options?.entrypoint) {
entrypoint = options.entrypoint.startsWith('.')
? resolve(root, options.entrypoint)
: options.entrypoint;
}
},
resolveId(id) {
if (id === virtualModuleId) {
return resolvedVirtualModuleId;
}
},
load(id) {
if (id === resolvedVirtualModuleId) {
if (entrypoint) {
return `\
import * as mod from ${JSON.stringify(entrypoint)};
export const setup = (Alpine) => {
if ('default' in mod) {
mod.default(Alpine);
} else {
${
!isBuild
? `console.warn("[@astrojs/alpinejs] entrypoint \`" + ${JSON.stringify(
entrypoint
)} + "\` does not export a default function. Check out https://docs.astro.build/en/guides/integrations-guide/alpinejs/#entrypoint.");`
: ''
}
}
}`;
}
return `export const setup = () => {};`;
}
},
};
}
export default function createPlugin(options?: Options): AstroIntegration {
return {
name: '@astrojs/alpinejs',
hooks: {
'astro:config:setup': ({ injectScript, updateConfig }) => {
// This gets injected into the user's page, so the import will pull
// from the project's version of Alpine.js in their package.json.
injectScript(
'page',
`import Alpine from 'alpinejs';
import { setup } from 'virtual:@astrojs/alpinejs/entrypoint';
setup(Alpine);
window.Alpine = Alpine;
Alpine.start();`
);
updateConfig({
vite: {
plugins: [virtualEntrypoint(options)],
},
});
},
},
};
}
|