vite-plugin-shopify-theme-islands 1.2.0 → 1.2.1
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/config-policy.d.ts +11 -0
- package/dist/index.d.ts +2 -65
- package/dist/index.js +117 -70
- package/dist/options.d.ts +64 -0
- package/dist/revive-bootstrap.d.ts +31 -0
- package/package.json +1 -1
- package/skills/custom-directives/SKILL.md +3 -2
- package/skills/directives/SKILL.md +3 -2
- package/skills/lifecycle/SKILL.md +3 -2
- package/skills/setup/SKILL.md +5 -3
- package/skills/writing-islands/SKILL.md +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ReviveOptions } from "./contract.js";
|
|
2
|
+
import type { ClientDirectiveDefinition, DirectivesConfig, ShopifyThemeIslandsOptions } from "./options.js";
|
|
3
|
+
export interface ResolvedThemeIslandsPolicy {
|
|
4
|
+
plugin: {
|
|
5
|
+
directives: DirectivesConfig;
|
|
6
|
+
customDirectives: ClientDirectiveDefinition[];
|
|
7
|
+
debug: boolean;
|
|
8
|
+
};
|
|
9
|
+
runtime: ReviveOptions;
|
|
10
|
+
}
|
|
11
|
+
export declare function resolveThemeIslandsPolicy(options?: ShopifyThemeIslandsOptions): ResolvedThemeIslandsPolicy;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,71 +1,8 @@
|
|
|
1
|
+
import type { ShopifyThemeIslandsOptions } from "./options.js";
|
|
1
2
|
import type { Plugin } from "vite";
|
|
2
3
|
/** A function that triggers the load of an island module. */
|
|
3
4
|
export type ClientDirectiveLoader = () => Promise<void>;
|
|
4
5
|
export type { ClientDirective, ClientDirectiveOptions } from "./contract.js";
|
|
5
|
-
|
|
6
|
-
export interface ClientDirectiveDefinition {
|
|
7
|
-
/** HTML attribute name, e.g. `'client:on-click'` */
|
|
8
|
-
name: string;
|
|
9
|
-
/** Path to the directive module (supports Vite aliases) */
|
|
10
|
-
entrypoint: string;
|
|
11
|
-
}
|
|
12
|
-
/** Shared directive configuration shape used by both the plugin and the runtime. */
|
|
13
|
-
export interface DirectivesConfig {
|
|
14
|
-
/** Configuration for the `client:visible` directive (IntersectionObserver). */
|
|
15
|
-
visible?: {
|
|
16
|
-
/** HTML attribute name. Default: `'client:visible'` */
|
|
17
|
-
attribute?: string;
|
|
18
|
-
/** Passed to IntersectionObserver — loads islands before they scroll into view. Default: `'200px'` */
|
|
19
|
-
rootMargin?: string;
|
|
20
|
-
/** Passed to IntersectionObserver — ratio of element that must be visible. Default: `0` */
|
|
21
|
-
threshold?: number;
|
|
22
|
-
};
|
|
23
|
-
/** Configuration for the `client:idle` directive (requestIdleCallback). */
|
|
24
|
-
idle?: {
|
|
25
|
-
/** HTML attribute name. Default: `'client:idle'` */
|
|
26
|
-
attribute?: string;
|
|
27
|
-
/** Deadline (ms) passed to requestIdleCallback; also used as the setTimeout fallback delay. Default: `500` */
|
|
28
|
-
timeout?: number;
|
|
29
|
-
};
|
|
30
|
-
/** Configuration for the `client:media` directive (matchMedia). */
|
|
31
|
-
media?: {
|
|
32
|
-
/** HTML attribute name. Default: `'client:media'` */
|
|
33
|
-
attribute?: string;
|
|
34
|
-
};
|
|
35
|
-
/** Configuration for the `client:defer` directive (fixed setTimeout delay). */
|
|
36
|
-
defer?: {
|
|
37
|
-
/** HTML attribute name. Default: `'client:defer'` */
|
|
38
|
-
attribute?: string;
|
|
39
|
-
/** Fallback delay (ms) when the attribute has no value. Default: `3000` */
|
|
40
|
-
delay?: number;
|
|
41
|
-
};
|
|
42
|
-
/** Configuration for the `client:interaction` directive (mouseenter/touchstart/focusin). */
|
|
43
|
-
interaction?: {
|
|
44
|
-
/** HTML attribute name. Default: `'client:interaction'` */
|
|
45
|
-
attribute?: string;
|
|
46
|
-
/** DOM event names to listen for. Default: `['mouseenter', 'touchstart', 'focusin']` */
|
|
47
|
-
events?: string[];
|
|
48
|
-
};
|
|
49
|
-
/** Custom client directives to register. Each entry maps an attribute name to a module entrypoint. */
|
|
50
|
-
custom?: ClientDirectiveDefinition[];
|
|
51
|
-
}
|
|
52
|
-
/** Event detail and runtime options (single source of truth in contract). */
|
|
53
|
-
import type { RetryConfig } from "./contract.js";
|
|
6
|
+
export type { ClientDirectiveDefinition, DirectivesConfig, ShopifyThemeIslandsOptions, } from "./options.js";
|
|
54
7
|
export type { IslandLoadDetail, IslandErrorDetail, ReviveOptions, RetryConfig, RuntimeDirectivesConfig, } from "./contract.js";
|
|
55
|
-
export interface ShopifyThemeIslandsOptions {
|
|
56
|
-
/** Directories to scan for island files. Accepts paths or Vite aliases. Default: `['/frontend/js/islands/']` */
|
|
57
|
-
directories?: string | string[];
|
|
58
|
-
/** Log discovered islands and generated virtual module. Default: `false` */
|
|
59
|
-
debug?: boolean;
|
|
60
|
-
/** Per-directive configuration. */
|
|
61
|
-
directives?: DirectivesConfig;
|
|
62
|
-
/** Automatic retry behaviour for failed island loads. */
|
|
63
|
-
retry?: RetryConfig;
|
|
64
|
-
/**
|
|
65
|
-
* Milliseconds before a custom directive that never calls `load()` is considered timed out.
|
|
66
|
-
* When exceeded, `islands:error` is dispatched and the island is abandoned.
|
|
67
|
-
* Default: `0` (disabled).
|
|
68
|
-
*/
|
|
69
|
-
directiveTimeout?: number;
|
|
70
|
-
}
|
|
71
8
|
export default function shopifyThemeIslands(options?: ShopifyThemeIslandsOptions): Plugin;
|
package/dist/index.js
CHANGED
|
@@ -54,39 +54,6 @@ function collectTagNames(dir) {
|
|
|
54
54
|
return names;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
// src/revive-module.ts
|
|
58
|
-
function buildReviveModuleSource(params) {
|
|
59
|
-
const { runtimePath, directoryGlobs, islandPaths, customDirectives, reviveOptions } = params;
|
|
60
|
-
const directiveImportLines = customDirectives?.map(({ entrypoint }, index) => `import _directive${index} from ${JSON.stringify(entrypoint)};`) ?? [];
|
|
61
|
-
const globEntries = [
|
|
62
|
-
`{ ${directoryGlobs.map((glob) => `...import.meta.glob(${JSON.stringify(glob)})`).join(", ")} }`
|
|
63
|
-
];
|
|
64
|
-
if (islandPaths?.length)
|
|
65
|
-
globEntries.push(`import.meta.glob(${JSON.stringify(islandPaths)})`);
|
|
66
|
-
const lines = [
|
|
67
|
-
...directiveImportLines,
|
|
68
|
-
`import { revive as _islands } from ${JSON.stringify(runtimePath)};`,
|
|
69
|
-
`const islands = Object.assign({}, ${globEntries.join(", ")});`,
|
|
70
|
-
`const options = ${JSON.stringify(reviveOptions)};`
|
|
71
|
-
];
|
|
72
|
-
if (customDirectives?.length) {
|
|
73
|
-
const customDirectivesMapLines = customDirectives.map(({ name }, index) => ` [${JSON.stringify(name)}, _directive${index}]`);
|
|
74
|
-
lines.push(`const customDirectives = new Map([
|
|
75
|
-
${customDirectivesMapLines.join(`,
|
|
76
|
-
`)}
|
|
77
|
-
]);`);
|
|
78
|
-
lines.push(`const payload = { islands, options, customDirectives };`);
|
|
79
|
-
} else {
|
|
80
|
-
lines.push(`const payload = { islands, options };`);
|
|
81
|
-
}
|
|
82
|
-
lines.push(`export const { disconnect } = _islands(payload);`);
|
|
83
|
-
return lines.join(`
|
|
84
|
-
`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/index.ts
|
|
88
|
-
import { fileURLToPath } from "node:url";
|
|
89
|
-
|
|
90
57
|
// src/contract.ts
|
|
91
58
|
var DEFAULT_DIRECTIVES = {
|
|
92
59
|
visible: { attribute: "client:visible", rootMargin: "200px", threshold: 0 },
|
|
@@ -137,13 +104,17 @@ function buildIslandMap(payload) {
|
|
|
137
104
|
return map;
|
|
138
105
|
}
|
|
139
106
|
|
|
140
|
-
// src/
|
|
141
|
-
var VIRTUAL_ID = "vite-plugin-shopify-theme-islands/revive";
|
|
142
|
-
var RESOLVED_ID = "\x00" + VIRTUAL_ID;
|
|
143
|
-
var ISLAND_ID = "vite-plugin-shopify-theme-islands/island";
|
|
144
|
-
var runtimePath = fileURLToPath(new URL("./runtime.js", import.meta.url));
|
|
145
|
-
var islandPath = fileURLToPath(new URL("./island.js", import.meta.url));
|
|
107
|
+
// src/config-policy.ts
|
|
146
108
|
var PREFIX = "[vite-plugin-shopify-theme-islands]";
|
|
109
|
+
function mergeDirectives(directives) {
|
|
110
|
+
return {
|
|
111
|
+
visible: { ...DEFAULT_DIRECTIVES.visible, ...directives?.visible },
|
|
112
|
+
idle: { ...DEFAULT_DIRECTIVES.idle, ...directives?.idle },
|
|
113
|
+
media: { ...DEFAULT_DIRECTIVES.media, ...directives?.media },
|
|
114
|
+
defer: { ...DEFAULT_DIRECTIVES.defer, ...directives?.defer },
|
|
115
|
+
interaction: { ...DEFAULT_DIRECTIVES.interaction, ...directives?.interaction }
|
|
116
|
+
};
|
|
117
|
+
}
|
|
147
118
|
function validateOptions(options, directives) {
|
|
148
119
|
const customDefs = options.directives?.custom ?? [];
|
|
149
120
|
if (Array.isArray(options.directories) && options.directories.length === 0) {
|
|
@@ -180,6 +151,93 @@ function validateOptions(options, directives) {
|
|
|
180
151
|
seen.add(def.name);
|
|
181
152
|
}
|
|
182
153
|
}
|
|
154
|
+
function resolveThemeIslandsPolicy(options = {}) {
|
|
155
|
+
const directives = mergeDirectives(options.directives);
|
|
156
|
+
validateOptions(options, directives);
|
|
157
|
+
const customDirectives = options.directives?.custom ?? [];
|
|
158
|
+
const debug = options.debug ?? false;
|
|
159
|
+
const runtime = {
|
|
160
|
+
directives,
|
|
161
|
+
debug,
|
|
162
|
+
...options.retry !== undefined ? { retry: options.retry } : {},
|
|
163
|
+
...options.directiveTimeout !== undefined ? { directiveTimeout: options.directiveTimeout } : {}
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
plugin: {
|
|
167
|
+
directives,
|
|
168
|
+
customDirectives,
|
|
169
|
+
debug
|
|
170
|
+
},
|
|
171
|
+
runtime
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// src/revive-module.ts
|
|
176
|
+
function buildReviveModuleSource(params) {
|
|
177
|
+
const { runtimePath, directoryGlobs, islandPaths, customDirectives, reviveOptions } = params;
|
|
178
|
+
const directiveImportLines = customDirectives?.map(({ entrypoint }, index) => `import _directive${index} from ${JSON.stringify(entrypoint)};`) ?? [];
|
|
179
|
+
const globEntries = [
|
|
180
|
+
`{ ${directoryGlobs.map((glob) => `...import.meta.glob(${JSON.stringify(glob)})`).join(", ")} }`
|
|
181
|
+
];
|
|
182
|
+
if (islandPaths?.length)
|
|
183
|
+
globEntries.push(`import.meta.glob(${JSON.stringify(islandPaths)})`);
|
|
184
|
+
const lines = [
|
|
185
|
+
...directiveImportLines,
|
|
186
|
+
`import { revive as _islands } from ${JSON.stringify(runtimePath)};`,
|
|
187
|
+
`const islands = Object.assign({}, ${globEntries.join(", ")});`,
|
|
188
|
+
`const options = ${JSON.stringify(reviveOptions)};`
|
|
189
|
+
];
|
|
190
|
+
if (customDirectives?.length) {
|
|
191
|
+
const customDirectivesMapLines = customDirectives.map(({ name }, index) => ` [${JSON.stringify(name)}, _directive${index}]`);
|
|
192
|
+
lines.push(`const customDirectives = new Map([
|
|
193
|
+
${customDirectivesMapLines.join(`,
|
|
194
|
+
`)}
|
|
195
|
+
]);`);
|
|
196
|
+
lines.push(`const payload = { islands, options, customDirectives };`);
|
|
197
|
+
} else {
|
|
198
|
+
lines.push(`const payload = { islands, options };`);
|
|
199
|
+
}
|
|
200
|
+
lines.push(`export const { disconnect } = _islands(payload);`);
|
|
201
|
+
return lines.join(`
|
|
202
|
+
`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/revive-bootstrap.ts
|
|
206
|
+
function createReviveBootstrapCompiler(ports, runtimePath) {
|
|
207
|
+
return {
|
|
208
|
+
async plan(input) {
|
|
209
|
+
const islandPaths = input.islandFiles.size > 0 ? ports.toLoadPaths(input.islandFiles, input.root) : null;
|
|
210
|
+
const customDirectives = input.customDirectives?.length ? await Promise.all(input.customDirectives.map(async ({ name, entrypoint }) => ({
|
|
211
|
+
name,
|
|
212
|
+
entrypoint: await ports.resolveEntrypoint(entrypoint)
|
|
213
|
+
}))) : null;
|
|
214
|
+
return {
|
|
215
|
+
runtimePath,
|
|
216
|
+
directoryGlobs: input.directories.map((dir) => dir + "**/*.{ts,js}"),
|
|
217
|
+
islandPaths,
|
|
218
|
+
customDirectives,
|
|
219
|
+
reviveOptions: input.reviveOptions
|
|
220
|
+
};
|
|
221
|
+
},
|
|
222
|
+
emit(plan) {
|
|
223
|
+
return buildReviveModuleSource({
|
|
224
|
+
runtimePath: plan.runtimePath,
|
|
225
|
+
directoryGlobs: plan.directoryGlobs,
|
|
226
|
+
islandPaths: plan.islandPaths,
|
|
227
|
+
customDirectives: plan.customDirectives?.length ? plan.customDirectives : undefined,
|
|
228
|
+
reviveOptions: plan.reviveOptions
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/index.ts
|
|
235
|
+
import { fileURLToPath } from "node:url";
|
|
236
|
+
var VIRTUAL_ID = "vite-plugin-shopify-theme-islands/revive";
|
|
237
|
+
var RESOLVED_ID = "\x00" + VIRTUAL_ID;
|
|
238
|
+
var ISLAND_ID = "vite-plugin-shopify-theme-islands/island";
|
|
239
|
+
var runtimePath = fileURLToPath(new URL("./runtime.js", import.meta.url));
|
|
240
|
+
var islandPath = fileURLToPath(new URL("./island.js", import.meta.url));
|
|
183
241
|
var defaultDirectories = ["/frontend/js/islands/"];
|
|
184
242
|
function normalizeDir(dir) {
|
|
185
243
|
return dir.endsWith("/") ? dir : dir + "/";
|
|
@@ -198,16 +256,9 @@ function resolveAliases(dirs, config) {
|
|
|
198
256
|
}
|
|
199
257
|
function shopifyThemeIslands(options = {}) {
|
|
200
258
|
const rawDirs = (Array.isArray(options.directories) ? options.directories : [options.directories ?? defaultDirectories[0]]).map(normalizeDir);
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
media: { ...DEFAULT_DIRECTIVES.media, ...options.directives?.media },
|
|
205
|
-
defer: { ...DEFAULT_DIRECTIVES.defer, ...options.directives?.defer },
|
|
206
|
-
interaction: { ...DEFAULT_DIRECTIVES.interaction, ...options.directives?.interaction }
|
|
207
|
-
};
|
|
208
|
-
const clientDirectiveDefinitions = options.directives?.custom ?? [];
|
|
209
|
-
validateOptions(options, directives);
|
|
210
|
-
const debug = options.debug ?? false;
|
|
259
|
+
const policy = resolveThemeIslandsPolicy(options);
|
|
260
|
+
const { directives, customDirectives: clientDirectiveDefinitions, debug } = policy.plugin;
|
|
261
|
+
const { runtime: reviveOptions } = policy;
|
|
211
262
|
const log = debug ? (...args) => console.log("[islands]", ...args) : () => {};
|
|
212
263
|
let resolvedDirs = rawDirs;
|
|
213
264
|
let root = process.cwd();
|
|
@@ -284,28 +335,24 @@ function shopifyThemeIslands(options = {}) {
|
|
|
284
335
|
async load(id) {
|
|
285
336
|
if (id !== RESOLVED_ID)
|
|
286
337
|
return;
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
customDirectives,
|
|
302
|
-
reviveOptions
|
|
303
|
-
directives,
|
|
304
|
-
debug,
|
|
305
|
-
retry: options.retry,
|
|
306
|
-
directiveTimeout: options.directiveTimeout
|
|
307
|
-
}
|
|
338
|
+
const compiler = createReviveBootstrapCompiler({
|
|
339
|
+
resolveEntrypoint: async (entrypoint) => {
|
|
340
|
+
const resolved = await this.resolve(entrypoint);
|
|
341
|
+
if (!resolved) {
|
|
342
|
+
throw new Error(`[vite-plugin-shopify-theme-islands] Cannot resolve custom directive entrypoint: "${entrypoint}"`);
|
|
343
|
+
}
|
|
344
|
+
return resolved.id;
|
|
345
|
+
},
|
|
346
|
+
toLoadPaths: getIslandPathsForLoad
|
|
347
|
+
}, runtimePath);
|
|
348
|
+
const plan = await compiler.plan({
|
|
349
|
+
root,
|
|
350
|
+
directories: resolvedDirs,
|
|
351
|
+
islandFiles,
|
|
352
|
+
customDirectives: clientDirectiveDefinitions,
|
|
353
|
+
reviveOptions
|
|
308
354
|
});
|
|
355
|
+
return compiler.emit(plan);
|
|
309
356
|
}
|
|
310
357
|
};
|
|
311
358
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { RetryConfig } from "./contract.js";
|
|
2
|
+
/** Plugin option entry for registering a custom client directive. */
|
|
3
|
+
export interface ClientDirectiveDefinition {
|
|
4
|
+
/** HTML attribute name, e.g. `'client:on-click'` */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Path to the directive module (supports Vite aliases) */
|
|
7
|
+
entrypoint: string;
|
|
8
|
+
}
|
|
9
|
+
/** Shared directive configuration shape used by both the plugin and the runtime. */
|
|
10
|
+
export interface DirectivesConfig {
|
|
11
|
+
/** Configuration for the `client:visible` directive (IntersectionObserver). */
|
|
12
|
+
visible?: {
|
|
13
|
+
/** HTML attribute name. Default: `'client:visible'` */
|
|
14
|
+
attribute?: string;
|
|
15
|
+
/** Passed to IntersectionObserver — loads islands before they scroll into view. Default: `'200px'` */
|
|
16
|
+
rootMargin?: string;
|
|
17
|
+
/** Passed to IntersectionObserver — ratio of element that must be visible. Default: `0` */
|
|
18
|
+
threshold?: number;
|
|
19
|
+
};
|
|
20
|
+
/** Configuration for the `client:idle` directive (requestIdleCallback). */
|
|
21
|
+
idle?: {
|
|
22
|
+
/** HTML attribute name. Default: `'client:idle'` */
|
|
23
|
+
attribute?: string;
|
|
24
|
+
/** Deadline (ms) passed to requestIdleCallback; also used as the setTimeout fallback delay. Default: `500` */
|
|
25
|
+
timeout?: number;
|
|
26
|
+
};
|
|
27
|
+
/** Configuration for the `client:media` directive (matchMedia). */
|
|
28
|
+
media?: {
|
|
29
|
+
/** HTML attribute name. Default: `'client:media'` */
|
|
30
|
+
attribute?: string;
|
|
31
|
+
};
|
|
32
|
+
/** Configuration for the `client:defer` directive (fixed setTimeout delay). */
|
|
33
|
+
defer?: {
|
|
34
|
+
/** HTML attribute name. Default: `'client:defer'` */
|
|
35
|
+
attribute?: string;
|
|
36
|
+
/** Fallback delay (ms) when the attribute has no value. Default: `3000` */
|
|
37
|
+
delay?: number;
|
|
38
|
+
};
|
|
39
|
+
/** Configuration for the `client:interaction` directive (mouseenter/touchstart/focusin). */
|
|
40
|
+
interaction?: {
|
|
41
|
+
/** HTML attribute name. Default: `'client:interaction'` */
|
|
42
|
+
attribute?: string;
|
|
43
|
+
/** DOM event names to listen for. Default: `['mouseenter', 'touchstart', 'focusin']` */
|
|
44
|
+
events?: string[];
|
|
45
|
+
};
|
|
46
|
+
/** Custom client directives to register. Each entry maps an attribute name to a module entrypoint. */
|
|
47
|
+
custom?: ClientDirectiveDefinition[];
|
|
48
|
+
}
|
|
49
|
+
export interface ShopifyThemeIslandsOptions {
|
|
50
|
+
/** Directories to scan for island files. Accepts paths or Vite aliases. Default: `['/frontend/js/islands/']` */
|
|
51
|
+
directories?: string | string[];
|
|
52
|
+
/** Log discovered islands and generated virtual module. Default: `false` */
|
|
53
|
+
debug?: boolean;
|
|
54
|
+
/** Per-directive configuration. */
|
|
55
|
+
directives?: DirectivesConfig;
|
|
56
|
+
/** Automatic retry behaviour for failed island loads. */
|
|
57
|
+
retry?: RetryConfig;
|
|
58
|
+
/**
|
|
59
|
+
* Milliseconds before a custom directive that never calls `load()` is considered timed out.
|
|
60
|
+
* When exceeded, `islands:error` is dispatched and the island is abandoned.
|
|
61
|
+
* Default: `0` (disabled).
|
|
62
|
+
*/
|
|
63
|
+
directiveTimeout?: number;
|
|
64
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ReviveOptions } from "./contract.js";
|
|
2
|
+
export interface ResolvedCustomDirective {
|
|
3
|
+
name: string;
|
|
4
|
+
entrypoint: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ReviveBootstrapInputs {
|
|
7
|
+
root: string;
|
|
8
|
+
directories: string[];
|
|
9
|
+
islandFiles: Set<string>;
|
|
10
|
+
customDirectives?: Array<{
|
|
11
|
+
name: string;
|
|
12
|
+
entrypoint: string;
|
|
13
|
+
}>;
|
|
14
|
+
reviveOptions: ReviveOptions;
|
|
15
|
+
}
|
|
16
|
+
export interface ReviveBootstrapPlan {
|
|
17
|
+
runtimePath: string;
|
|
18
|
+
directoryGlobs: string[];
|
|
19
|
+
islandPaths: string[] | null;
|
|
20
|
+
customDirectives: ResolvedCustomDirective[] | null;
|
|
21
|
+
reviveOptions: ReviveOptions;
|
|
22
|
+
}
|
|
23
|
+
export interface ReviveBootstrapCompilerPorts {
|
|
24
|
+
resolveEntrypoint(entrypoint: string): Promise<string>;
|
|
25
|
+
toLoadPaths(islandFiles: Set<string>, root: string): string[];
|
|
26
|
+
}
|
|
27
|
+
export interface ReviveBootstrapCompiler {
|
|
28
|
+
plan(input: ReviveBootstrapInputs): Promise<ReviveBootstrapPlan>;
|
|
29
|
+
emit(plan: ReviveBootstrapPlan): string;
|
|
30
|
+
}
|
|
31
|
+
export declare function createReviveBootstrapCompiler(ports: ReviveBootstrapCompilerPorts, runtimePath: string): ReviveBootstrapCompiler;
|
package/package.json
CHANGED
|
@@ -9,11 +9,12 @@ description: >
|
|
|
9
9
|
built-in conditions resolve.
|
|
10
10
|
type: core
|
|
11
11
|
library: vite-plugin-shopify-theme-islands
|
|
12
|
-
library_version: "1.2.
|
|
12
|
+
library_version: "1.2.1"
|
|
13
13
|
sources:
|
|
14
14
|
- Rees1993/vite-plugin-shopify-theme-islands:src/contract.ts
|
|
15
15
|
- Rees1993/vite-plugin-shopify-theme-islands:src/index.ts
|
|
16
16
|
- Rees1993/vite-plugin-shopify-theme-islands:src/runtime.ts
|
|
17
|
+
- Rees1993/vite-plugin-shopify-theme-islands:src/config-policy.ts
|
|
17
18
|
---
|
|
18
19
|
|
|
19
20
|
## Setup
|
|
@@ -222,7 +223,7 @@ shopifyThemeIslands({
|
|
|
222
223
|
|
|
223
224
|
Custom directive names must be unique and must not collide with any built-in directive name, including renamed built-ins.
|
|
224
225
|
|
|
225
|
-
Source: src/
|
|
226
|
+
Source: src/config-policy.ts — validateOptions() duplicate and built-in conflict checks
|
|
226
227
|
|
|
227
228
|
### HIGH Entrypoint path missing `./` prefix
|
|
228
229
|
|
|
@@ -9,10 +9,11 @@ description: >
|
|
|
9
9
|
client:interaction values warn and fall back to default events.
|
|
10
10
|
type: core
|
|
11
11
|
library: vite-plugin-shopify-theme-islands
|
|
12
|
-
library_version: "1.2.
|
|
12
|
+
library_version: "1.2.1"
|
|
13
13
|
sources:
|
|
14
14
|
- Rees1993/vite-plugin-shopify-theme-islands:src/runtime.ts
|
|
15
15
|
- Rees1993/vite-plugin-shopify-theme-islands:src/index.ts
|
|
16
|
+
- Rees1993/vite-plugin-shopify-theme-islands:src/options.ts
|
|
16
17
|
---
|
|
17
18
|
|
|
18
19
|
## Setup
|
|
@@ -261,4 +262,4 @@ Correct:
|
|
|
261
262
|
|
|
262
263
|
When `directives.visible.attribute` (or any directive's `attribute` option) is overridden in `vite.config.ts`, all Liquid templates must use the configured name. The default `client:*` names no longer apply. Always read `vite.config.ts` to check for overridden attribute names before writing directives in Liquid.
|
|
263
264
|
|
|
264
|
-
Source: src/
|
|
265
|
+
Source: src/options.ts:DirectivesConfig — `attribute` field per directive; src/runtime.ts reads configured attribute names at runtime
|
|
@@ -11,11 +11,12 @@ description: >
|
|
|
11
11
|
teardown.
|
|
12
12
|
type: core
|
|
13
13
|
library: vite-plugin-shopify-theme-islands
|
|
14
|
-
library_version: "1.2.
|
|
14
|
+
library_version: "1.2.1"
|
|
15
15
|
sources:
|
|
16
16
|
- Rees1993/vite-plugin-shopify-theme-islands:src/events.ts
|
|
17
17
|
- Rees1993/vite-plugin-shopify-theme-islands:src/contract.ts
|
|
18
18
|
- Rees1993/vite-plugin-shopify-theme-islands:src/runtime.ts
|
|
19
|
+
- Rees1993/vite-plugin-shopify-theme-islands:src/revive-module.ts
|
|
19
20
|
---
|
|
20
21
|
|
|
21
22
|
## Setup
|
|
@@ -144,7 +145,7 @@ import { disconnect } from "vite-plugin-shopify-theme-islands/revive";
|
|
|
144
145
|
|
|
145
146
|
Only the virtual module (`/revive`) exports the `disconnect` bound to the plugin-managed `revive()` instance. Importing from other entry points references a different or nonexistent instance.
|
|
146
147
|
|
|
147
|
-
Source: src/
|
|
148
|
+
Source: src/revive-module.ts — buildReviveModuleSource() emits `export const { disconnect } = _islands(payload)`
|
|
148
149
|
|
|
149
150
|
### MEDIUM `onIslandError` fires on every retry, not just final failure
|
|
150
151
|
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -10,10 +10,12 @@ description: >
|
|
|
10
10
|
directive timeout.
|
|
11
11
|
type: core
|
|
12
12
|
library: vite-plugin-shopify-theme-islands
|
|
13
|
-
library_version: "1.2.
|
|
13
|
+
library_version: "1.2.1"
|
|
14
14
|
sources:
|
|
15
15
|
- Rees1993/vite-plugin-shopify-theme-islands:src/index.ts
|
|
16
16
|
- Rees1993/vite-plugin-shopify-theme-islands:src/contract.ts
|
|
17
|
+
- Rees1993/vite-plugin-shopify-theme-islands:src/options.ts
|
|
18
|
+
- Rees1993/vite-plugin-shopify-theme-islands:src/config-policy.ts
|
|
17
19
|
---
|
|
18
20
|
|
|
19
21
|
## Setup
|
|
@@ -207,7 +209,7 @@ shopifyThemeIslands({
|
|
|
207
209
|
|
|
208
210
|
`directives` accepts only `visible`, `idle`, `media`, `defer`, `interaction`, and `custom`. `retry` at `directives.retry` is silently ignored.
|
|
209
211
|
|
|
210
|
-
Source: src/
|
|
212
|
+
Source: src/options.ts — ShopifyThemeIslandsOptions
|
|
211
213
|
|
|
212
214
|
### HIGH Wrong key name for retry count
|
|
213
215
|
|
|
@@ -250,4 +252,4 @@ shopifyThemeIslands({
|
|
|
250
252
|
|
|
251
253
|
`directiveTimeout` is a top-level plugin option, not part of the per-directive config object.
|
|
252
254
|
|
|
253
|
-
Source: src/
|
|
255
|
+
Source: src/options.ts — ShopifyThemeIslandsOptions
|
|
@@ -8,7 +8,7 @@ description: >
|
|
|
8
8
|
base class, and child island cascade behaviour.
|
|
9
9
|
type: core
|
|
10
10
|
library: vite-plugin-shopify-theme-islands
|
|
11
|
-
library_version: "1.2.
|
|
11
|
+
library_version: "1.2.1"
|
|
12
12
|
sources:
|
|
13
13
|
- Rees1993/vite-plugin-shopify-theme-islands:src/island.ts
|
|
14
14
|
- Rees1993/vite-plugin-shopify-theme-islands:src/discovery.ts
|