vite-plugin-shopify-theme-islands 1.0.0 → 1.0.2

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/index.js CHANGED
@@ -10,6 +10,42 @@ var islandPath = fileURLToPath(new URL("./island.js", import.meta.url));
10
10
  var ISLAND_IMPORT_RE = /from\s+['"]vite-plugin-shopify-theme-islands\/island['"]/;
11
11
  var TS_JS_RE = /\.(ts|js)$/;
12
12
  var SKIP_DIRS = new Set(["node_modules", "dist", "build", "public", "assets", ".cache"]);
13
+ var PREFIX = "[vite-plugin-shopify-theme-islands]";
14
+ function validateOptions(options, directives) {
15
+ const customDefs = options.directives?.custom ?? [];
16
+ if (Array.isArray(options.directories) && options.directories.length === 0) {
17
+ throw new Error(`${PREFIX} "directories" must not be empty`);
18
+ }
19
+ const threshold = options.directives?.visible?.threshold;
20
+ if (threshold !== undefined && (threshold < 0 || threshold > 1)) {
21
+ throw new Error(`${PREFIX} "directives.visible.threshold" must be between 0 and 1, got ${threshold}`);
22
+ }
23
+ if (options.retry !== undefined) {
24
+ const { retries, delay } = options.retry;
25
+ if (retries !== undefined && retries < 0) {
26
+ throw new Error(`${PREFIX} "retry.retries" must be >= 0, got ${retries}`);
27
+ }
28
+ if (delay !== undefined && delay < 0) {
29
+ throw new Error(`${PREFIX} "retry.delay" must be >= 0, got ${delay}`);
30
+ }
31
+ }
32
+ const builtinAttributes = new Set([
33
+ directives.visible.attribute,
34
+ directives.idle.attribute,
35
+ directives.media.attribute,
36
+ directives.defer.attribute
37
+ ]);
38
+ const seen = new Set;
39
+ for (const def of customDefs) {
40
+ if (seen.has(def.name)) {
41
+ throw new Error(`${PREFIX} Duplicate custom directive name: "${def.name}"`);
42
+ }
43
+ if (builtinAttributes.has(def.name)) {
44
+ throw new Error(`${PREFIX} Custom directive "${def.name}" conflicts with a built-in directive`);
45
+ }
46
+ seen.add(def.name);
47
+ }
48
+ }
13
49
  var defaults = {
14
50
  directories: ["/frontend/js/islands/"],
15
51
  directives: {
@@ -71,6 +107,7 @@ function shopifyThemeIslands(options = {}) {
71
107
  defer: { ...defaults.directives.defer, ...options.directives?.defer }
72
108
  };
73
109
  const clientDirectiveDefinitions = options.directives?.custom ?? [];
110
+ validateOptions(options, directives);
74
111
  const debug = options.debug ?? false;
75
112
  const log = debug ? (...args) => console.log("[islands]", ...args) : () => {};
76
113
  let resolvedDirs = rawDirs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-shopify-theme-islands",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Vite plugin for island architecture in Shopify themes",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.3.10",
@@ -78,11 +78,11 @@
78
78
  },
79
79
  "devDependencies": {
80
80
  "@happy-dom/global-registrator": "^20.8.4",
81
- "@tanstack/intent": "^0.0.19",
81
+ "@tanstack/intent": "0.0.21",
82
82
  "@types/bun": "^1.3.10",
83
83
  "@types/node": "^22.0.0",
84
- "oxfmt": "^0.40.0",
85
- "oxlint": "^1.55.0",
84
+ "oxfmt": "0.41.0",
85
+ "oxlint": "1.56.0",
86
86
  "typescript": "^5.0.0",
87
87
  "vite": "^8.0.0"
88
88
  }
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: vite-plugin-shopify-theme-islands/custom-directives
2
+ name: custom-directives
3
3
  description: >
4
4
  Custom client directives registered via directives.custom in vite.config.ts.
5
5
  ClientDirective function signature (load, options, el). AND-latch: when
@@ -7,7 +7,7 @@ description: >
7
7
  the island activates. Error handling — thrown errors fire islands:error.
8
8
  type: core
9
9
  library: vite-plugin-shopify-theme-islands
10
- library_version: "1.0.0"
10
+ library_version: "1.0.2"
11
11
  sources:
12
12
  - Rees1993/vite-plugin-shopify-theme-islands:src/index.ts
13
13
  - Rees1993/vite-plugin-shopify-theme-islands:src/runtime.ts
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: vite-plugin-shopify-theme-islands/directives
2
+ name: directives
3
3
  description: >
4
4
  Built-in client directives: client:visible (IntersectionObserver, rootMargin),
5
5
  client:media (matchMedia query), client:idle (requestIdleCallback),
@@ -7,7 +7,7 @@ description: >
7
7
  all must resolve. Per-element value overrides. Empty client:media warning.
8
8
  type: core
9
9
  library: vite-plugin-shopify-theme-islands
10
- library_version: "1.0.0"
10
+ library_version: "1.0.2"
11
11
  sources:
12
12
  - Rees1993/vite-plugin-shopify-theme-islands:src/runtime.ts
13
13
  - Rees1993/vite-plugin-shopify-theme-islands:src/index.ts
@@ -165,3 +165,41 @@ Correct:
165
165
  The attribute value is passed directly to `IntersectionObserver` as `rootMargin`, fully replacing the global default.
166
166
 
167
167
  Source: src/runtime.ts — `await visible(el, visibleAttr || rootMargin, threshold, pendingVisible)`
168
+
169
+ ### HIGH Directive attribute typo — island loads without condition
170
+
171
+ Wrong:
172
+
173
+ ```html
174
+ <product-form client:visibled></product-form>
175
+ <product-form client:Visible></product-form>
176
+ ```
177
+
178
+ Correct:
179
+
180
+ ```html
181
+ <product-form client:visible></product-form>
182
+ ```
183
+
184
+ Directive attributes are case-sensitive. An unrecognised attribute is silently ignored — the island loads immediately as if no directive were set. No warning is emitted. Check for typos if an island activates earlier than expected.
185
+
186
+ Source: src/runtime.ts — runtime checks exact attribute names from plugin config
187
+
188
+ ### HIGH Agent uses default attribute name when developer has configured a custom one
189
+
190
+ Wrong:
191
+
192
+ ```html
193
+ <!-- developer has set visible.attribute: "data:visible" in vite.config.ts -->
194
+ <product-form client:visible></product-form>
195
+ ```
196
+
197
+ Correct:
198
+
199
+ ```html
200
+ <product-form data:visible></product-form>
201
+ ```
202
+
203
+ 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.
204
+
205
+ Source: src/index.ts:DirectivesConfig — `attribute` field per directive; src/runtime.ts reads configured attribute names at runtime
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: vite-plugin-shopify-theme-islands/lifecycle
2
+ name: lifecycle
3
3
  description: >
4
4
  Island lifecycle events and SPA teardown. onIslandLoad and onIslandError
5
5
  helpers from vite-plugin-shopify-theme-islands/events — prefer these over
@@ -8,7 +8,7 @@ description: >
8
8
  module revive for SPA navigation teardown.
9
9
  type: core
10
10
  library: vite-plugin-shopify-theme-islands
11
- library_version: "1.0.0"
11
+ library_version: "1.0.2"
12
12
  sources:
13
13
  - Rees1993/vite-plugin-shopify-theme-islands:src/events.ts
14
14
  - Rees1993/vite-plugin-shopify-theme-islands:src/index.ts
@@ -1,42 +1,59 @@
1
1
  ---
2
- name: vite-plugin-shopify-theme-islands/setup
2
+ name: setup
3
3
  description: >
4
- Plugin install and vite.config.ts configuration. Covers shopifyThemeIslands()
5
- options: directories (string | string[]), debug, directives deep-merge, and
6
- retry (retries, delay with exponential backoff). Load when configuring the
7
- plugin, setting island scan directories, or enabling retry.
4
+ Getting-started journey and plugin configuration. Covers the full path from
5
+ install to first working island. shopifyThemeIslands() options: directories
6
+ (string | string[]), debug, directives deep-merge, and retry (retries, delay
7
+ with exponential backoff). Load when setting up the plugin, configuring
8
+ island scan directories, or enabling retry.
8
9
  type: core
9
10
  library: vite-plugin-shopify-theme-islands
10
- library_version: "1.0.0"
11
+ library_version: "1.0.2"
11
12
  sources:
12
13
  - Rees1993/vite-plugin-shopify-theme-islands:src/index.ts
13
14
  ---
14
15
 
15
16
  ## Setup
16
17
 
18
+ This plugin is framework-agnostic but designed for Shopify themes. Most Shopify
19
+ projects also use
20
+ [vite-plugin-shopify](https://github.com/barrel/vite-plugin-shopify) to handle
21
+ Shopify-specific asset serving — if the project uses it, add this plugin
22
+ alongside it in the existing `plugins` array.
23
+
24
+ ### 1. Add the plugin to `vite.config.ts`
25
+
17
26
  ```ts
18
27
  // vite.config.ts
19
28
  import { defineConfig } from "vite";
20
29
  import shopifyThemeIslands from "vite-plugin-shopify-theme-islands";
21
30
 
22
31
  export default defineConfig({
23
- plugins: [
24
- shopifyThemeIslands({
25
- directories: ["/frontend/js/islands/"],
26
- debug: false,
27
- retry: { retries: 2, delay: 500 },
28
- }),
29
- ],
32
+ plugins: [shopifyThemeIslands()],
30
33
  });
31
34
  ```
32
35
 
33
- Import the virtual module in the theme JS entry point to activate islands:
36
+ All options are optional. The default islands directory is `/frontend/js/islands/`.
37
+
38
+ ### 2. Import the virtual module in the theme JS entry point
34
39
 
35
40
  ```ts
36
41
  // frontend/js/theme.ts
37
42
  import "vite-plugin-shopify-theme-islands/revive";
38
43
  ```
39
44
 
45
+ This activates the runtime — islands are never loaded without this import.
46
+
47
+ ### 3. Add directives to Liquid templates
48
+
49
+ ```html
50
+ <!-- sections/product.liquid -->
51
+ <product-form client:visible></product-form>
52
+ ```
53
+
54
+ That's a working setup. Islands in `/frontend/js/islands/` matching the tag
55
+ name are loaded lazily when the directive condition is met.
56
+
40
57
  ## Core Patterns
41
58
 
42
59
  ### Configure multiple island directories
@@ -101,6 +118,58 @@ The plugin generates the virtual module but has no effect until it is imported i
101
118
 
102
119
  Source: src/index.ts — VIRTUAL_ID / RESOLVED_ID
103
120
 
121
+ ### HIGH Agent hardcodes default values — unnecessary noise
122
+
123
+ Wrong:
124
+
125
+ ```ts
126
+ shopifyThemeIslands({
127
+ directories: ["/frontend/js/islands/"],
128
+ debug: false,
129
+ directives: {
130
+ visible: { attribute: "client:visible", rootMargin: "200px", threshold: 0 },
131
+ idle: { attribute: "client:idle", timeout: 500 },
132
+ media: { attribute: "client:media" },
133
+ defer: { attribute: "client:defer", delay: 3000 },
134
+ },
135
+ });
136
+ ```
137
+
138
+ Correct:
139
+
140
+ ```ts
141
+ shopifyThemeIslands();
142
+ ```
143
+
144
+ All options are optional and default to sensible values. Only include options that differ from the defaults.
145
+
146
+ ### HIGH Agent overwrites existing `vite.config.ts` instead of appending
147
+
148
+ Before adding the plugin, read the existing `vite.config.ts`. Projects commonly
149
+ already have `vite-plugin-shopify` or other plugins — the island plugin must be
150
+ added to the existing `plugins` array, not replace it.
151
+
152
+ Wrong:
153
+
154
+ ```ts
155
+ // Replaces existing plugins
156
+ export default defineConfig({
157
+ plugins: [shopifyThemeIslands()],
158
+ });
159
+ ```
160
+
161
+ Correct:
162
+
163
+ ```ts
164
+ // Appends to existing plugins
165
+ export default defineConfig({
166
+ plugins: [
167
+ shopify(), // pre-existing plugin preserved
168
+ shopifyThemeIslands(),
169
+ ],
170
+ });
171
+ ```
172
+
104
173
  ### HIGH `retry` nested inside `directives` — no retries happen
105
174
 
106
175
  Wrong:
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: vite-plugin-shopify-theme-islands/writing-islands
2
+ name: writing-islands
3
3
  description: >
4
4
  Writing island files. Two discovery modes: directory scanning (files in
5
5
  configured directories auto-discovered by tag name = filename) and Island
@@ -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.0.0"
11
+ library_version: "1.0.2"
12
12
  sources:
13
13
  - Rees1993/vite-plugin-shopify-theme-islands:src/island.ts
14
14
  - Rees1993/vite-plugin-shopify-theme-islands:src/runtime.ts