vite-plugin-vanjs 0.1.4 → 0.1.6

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 CHANGED
@@ -8,7 +8,7 @@
8
8
  [![vanjs-core version](https://img.shields.io/badge/vanjs--core-1.5.5-brightgreen)](https://github.com/vanjs-org/van)
9
9
  [![mini-van-plate version](https://img.shields.io/badge/mini--van--plate-0.6.3-brightgreen)](https://github.com/vanjs-org/mini-van-plate)
10
10
  [![vitest version](https://img.shields.io/badge/vitest-3.1.2-brightgreen)](https://www.vitest.dev/)
11
- [![vite version](https://img.shields.io/badge/vite-6.3.3-brightgreen)](https://vite.dev)
11
+ [![vite version](https://img.shields.io/badge/vite-6.3.4-brightgreen)](https://vite.dev)
12
12
 
13
13
  A mini meta-framework for [VanJS](https://vanjs.org/) developed around the awesome [vite](https://vite.dev) and tested with [vitest](https://vitest.dev). The plugin comes with a set of modules to streamline your workflow:
14
14
  * ***@vanjs/router*** - one of the most important part of an application which allows you to split code and lazy load page like components with ease, handles both Client Side Rendering (SSR) and Server Side Rendering (CSR) and makes it really easy to work with;
package/client/index.mjs CHANGED
@@ -36,8 +36,8 @@ export const styleToString = (style) => {
36
36
  : /* istanbul ignore next */ "";
37
37
  };
38
38
 
39
- /** @type {(el1: HTMLElement, el2: HTMLElement | HTMLElement[]) => boolean} */
40
- export function elementsMatch(el1, el2) {
39
+ /** @type {(el1: HTMLElement, el2: HTMLElement | HTMLElement[], deep?: boolean) => boolean} */
40
+ export function elementsMatch(el1, el2, deep) {
41
41
  // Quick initial checks before recursing
42
42
  // istanbul ignore else
43
43
  if (
@@ -63,15 +63,25 @@ export function elementsMatch(el1, el2) {
63
63
  child.querySelector("[data-hk]"))
64
64
  );
65
65
 
66
+ // istanbul ignore next
66
67
  if (!hasHydratedChildren) {
67
68
  return true; // If no hydrated children, elements match based on initial checks
68
69
  }
69
70
 
70
- return childNodes1.every((child, idx) =>
71
- elementsMatch(child, childNodes2[idx])
72
- );
71
+ // Only recurse if opted in
72
+ // istanbul ignore next
73
+ return deep
74
+ ? childNodes1.every((child, idx) => elementsMatch(child, childNodes2[idx]))
75
+ : true;
73
76
  }
74
77
 
78
+ /** @type {<E extends Element = Element, T extends keyof HTMLElementTagNameMap>(target: E, ...tagNames: T[]) => boolean} */
79
+ const isTag = (target, ...tagNames) => {
80
+ return tagNames.some((tag) =>
81
+ target.tagName.toLowerCase() === tag.toLowerCase()
82
+ );
83
+ };
84
+
75
85
  function createHydrationContext() {
76
86
  /** @type {WeakMap<Element, Element>} */
77
87
  const parentCache = new WeakMap();
@@ -106,13 +116,18 @@ function createHydrationContext() {
106
116
  return parent;
107
117
  }
108
118
 
109
- /** @type {(oldDom: HTMLElement, newDom: HTMLElement) => HTMLElement} */
119
+ /** @type {(oldDom: HTMLElement, newDom: HTMLElement | HTMLElement[]) => HTMLElement} */
110
120
  function diffAndHydrate(oldDom, newDom) {
111
121
  // SPA mode
112
122
  // istanbul ignore else
113
123
  if (!oldDom.children.length && !elementsMatch(oldDom, newDom)) {
114
124
  return oldDom.replaceChildren(...unwrap(newDom).children);
115
125
  }
126
+ // istanbul ignore else
127
+ if (newDom instanceof Array) {
128
+ oldDom.replaceChildren(...unwrap(newDom).children);
129
+ return;
130
+ }
116
131
 
117
132
  // SSR Mode
118
133
  /** @type {Set<HTMLElement>} */
@@ -175,12 +190,8 @@ export const hydrate = (target, content) => {
175
190
  const wrapper = unwrap(content);
176
191
  const currentChildren = Array.from(target.children);
177
192
  const newChildren = Array.from(wrapper.children);
178
- const isStyleLink = (tag) =>
179
- [HTMLStyleElement, HTMLLinkElement].some((e) => tag instanceof e);
180
- const isStyle = (tag) => tag instanceof HTMLStyleElement;
181
- const isLink = (tag) => tag instanceof HTMLLinkElement;
182
193
 
183
- if (target.tagName.toLowerCase() === "head") {
194
+ if (isTag(target, "head")) {
184
195
  // Keep current tags on first hydration
185
196
  if (!target.hasAttribute("data-h")) {
186
197
  target.setAttribute("data-h", "");
@@ -188,14 +199,18 @@ export const hydrate = (target, content) => {
188
199
  }
189
200
 
190
201
  // Handle non-style/link tags first
191
- const regularTags = newChildren.filter((child) => !isStyleLink(child));
202
+ const regularTags = newChildren.filter((child) =>
203
+ !isTag(child, "style", "link")
204
+ );
192
205
 
193
206
  // Handle style/link tags separately
194
- const styleTags = newChildren.filter((child) => isStyleLink(child));
207
+ const styleTags = newChildren.filter((child) =>
208
+ isTag(child, "style", "link")
209
+ );
195
210
 
196
211
  // Create maps for existing tags
197
212
  const existingStyles = new Map(
198
- currentChildren.filter(isStyleLink)
213
+ currentChildren.filter((child) => isTag(child, "style", "link"))
199
214
  .map((child) => [getTagKey(child), child]),
200
215
  );
201
216
 
@@ -219,29 +234,29 @@ export const hydrate = (target, content) => {
219
234
 
220
235
  // Skip if tag already exists with same content+id/href
221
236
  if (existing) {
222
- /* istanbul ignore next - try again later */
223
- if (isStyle(existing) && isStyle(newChild)) {
237
+ // istanbul ignore next - try again later
238
+ if (isTag(existing, "style") && isTag(newChild, "style")) {
224
239
  if (
225
240
  existing.textContent === newChild.textContent &&
226
241
  existing.id === newChild.id
227
242
  ) return;
228
243
  }
229
- /* istanbul ignore next - try again later */
230
- if (isLink(existing) && isLink(newChild)) {
244
+ // istanbul ignore next - try again later
245
+ if (isTag(existing, "link") && isTag(newChild, "link")) {
231
246
  if (existing.href === newChild.href) return;
232
247
  }
233
248
  }
234
249
 
235
250
  // For link tags, add with disabled state first
236
- /* istanbul ignore else - try again later */
237
- if (isLink(newChild)) {
251
+ // istanbul ignore else - try again later
252
+ if (isTag(newChild, "link")) {
238
253
  const temp = newChild.cloneNode();
239
254
  temp.disabled = true;
240
255
 
241
256
  const originalRel = temp.rel;
242
257
  temp.rel = "preload";
243
258
  temp.as = "style";
244
- /* istanbul ignore next */
259
+ // istanbul ignore next
245
260
  temp.onload = () => {
246
261
  temp.rel = originalRel;
247
262
  temp.removeAttribute("as");
@@ -253,9 +268,9 @@ export const hydrate = (target, content) => {
253
268
 
254
269
  target.appendChild(temp);
255
270
  } // For style tags, add new one first
256
- else if (isStyle(newChild)) {
271
+ else if (isTag(newChild, "style")) {
257
272
  target.appendChild(newChild);
258
- /* istanbul ignore next - try again later */
273
+ // istanbul ignore next - try again later
259
274
  if (existing && existing.parentNode === target) {
260
275
  // Remove old one in next frame
261
276
  existing.remove();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-vanjs",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "author": "thednp",
5
5
  "license": "MIT",
6
6
  "description": "A mini meta-framework for VanJS powered by Vite",
@@ -93,7 +93,7 @@
93
93
  "@vitest/ui": "^3.1.2",
94
94
  "happy-dom": "^16.8.1",
95
95
  "typescript": "5.6.2",
96
- "vite": "^6.3.3",
96
+ "vite": "^6.3.4",
97
97
  "vitest": "^3.1.2"
98
98
  },
99
99
  "packageManager": "pnpm@8.6.12",
package/plugin/types.d.ts CHANGED
@@ -6,18 +6,15 @@ export * from "../meta/types";
6
6
  export * from "../server/types";
7
7
  export * from "../client/types";
8
8
  export * from "../parser/types";
9
- import type { Plugin } from "vite";
9
+ import type { PluginOption } from "vite";
10
10
 
11
11
  export type VanJSPluginOptions = {
12
12
  routesDir: string;
13
13
  extensions: string[];
14
14
  };
15
15
 
16
- export type VanJSPlugin = (
17
- options?: Partial<VanJSPluginOptions>,
18
- ) => Plugin;
19
-
20
- // This is what your plugin actually returns, so declare it as a Plugin type
21
- declare const VitePluginVanJS: VanJSPlugin;
16
+ export declare const VitePluginVanJS: (
17
+ config?: VitePluginVanJS,
18
+ ) => PluginOption<VanJSPluginOptions>;
22
19
 
23
20
  export default VitePluginVanJS;
@@ -1,12 +1,30 @@
1
1
  import { dummyVanX, registerEnv } from "mini-van-plate/shared";
2
2
 
3
+ const {
4
+ calc,
5
+ compact,
6
+ list,
7
+ noreactive,
8
+ raw,
9
+ reactive,
10
+ replace,
11
+ stateFields,
12
+ } = dummyVanX;
13
+
3
14
  const vanX = {
4
- ...dummyVanX,
5
- get default() {
6
- return dummyVanX;
7
- },
15
+ calc,
16
+ compact,
17
+ list,
18
+ noreactive,
19
+ raw,
20
+ reactive,
21
+ replace,
22
+ stateFields,
8
23
  };
9
24
 
10
25
  registerEnv({ vanX });
11
26
 
12
- export default vanX;
27
+ export { calc, compact, list, noreactive, raw, reactive, replace, stateFields };
28
+
29
+ export { vanX as default };
30
+ export {};
package/setup/vanX.mjs CHANGED
@@ -20,14 +20,11 @@ const vanX = {
20
20
  list,
21
21
  replace,
22
22
  compact,
23
- // Define default as part of the initial object
24
- get default() {
25
- return vanX;
26
- },
27
23
  };
28
24
 
29
25
  // Export named exports
30
26
  export { calc, compact, list, noreactive, raw, reactive, replace, stateFields };
31
27
 
32
28
  // Export as default
33
- export default vanX;
29
+ export { vanX as default };
30
+ export {};