vite-plugin-vanjs 0.0.5 → 0.0.7
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 +32 -34
- package/client/global.d.ts +5 -1
- package/client/index.mjs +99 -5
- package/client/types.d.ts +5 -1
- package/jsx/global.d.ts +3 -2
- package/jsx/jsx.d.ts +42 -9
- package/jsx/jsx.mjs +10 -10
- package/meta/Head.mjs +3 -3
- package/meta/global.d.ts +24 -12
- package/meta/helpers.mjs +5 -3
- package/meta/tags.mjs +5 -7
- package/meta/types.d.ts +7 -7
- package/package.json +8 -7
- package/router/a.mjs +14 -8
- package/router/global.d.ts +75 -16
- package/router/helpers.mjs +26 -7
- package/router/lazy.mjs +1 -1
- package/router/router.mjs +17 -10
- package/router/state.mjs +3 -2
- package/router/types.d.ts +86 -22
- package/server/global.d.ts +1 -0
- package/server/index.mjs +3 -3
- package/server/types.d.ts +1 -1
- package/setup/index-debug.mjs +21 -0
- package/setup/van-debug.mjs +2 -0
- package/src/index.mjs +18 -2
- package/src/types.d.ts +1 -1
- package/tsconfig.json +1 -1
package/README.md
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
[](https://github.com/vanjs-org/van)
|
|
9
9
|
[](https://github.com/vanjs-org/mini-van-plate)
|
|
10
|
-
[](https://www.vitest.dev/)
|
|
11
|
+
[](https://vite.dev)
|
|
12
12
|
|
|
13
13
|
A mini meta-framework for [VanJS](https://vanjs.org/) developed around the awesome [Vite](https://vite.dev). The plugin comes with a set of modules to simplify your workflow:
|
|
14
|
-
* ***@vanjs/router*** - one of the most important part of an application
|
|
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;
|
|
15
15
|
* ***@vanjs/meta*** - allows you to create metadata for your pages as well as load additional assets with ease;
|
|
16
16
|
* ***@vanjs/jsx*** - enables JSX transformation;
|
|
17
17
|
* ***@vanjs/setup*** - enables loading VanJS modules isomorphically;
|
|
@@ -21,38 +21,33 @@ A mini meta-framework for [VanJS](https://vanjs.org/) developed around the aweso
|
|
|
21
21
|
The plugin will automatically load the appropriate Van or VanX objects depending on the client/server environment with zero configuration needed. It uses the `mini-van-plate/shared` module to register the required objects in an isomorphic enviroment.
|
|
22
22
|
|
|
23
23
|
### Notes
|
|
24
|
-
* The plugin uses `van-ext` along with `mini-van-plate` so you can have everything ready from start.
|
|
24
|
+
* The plugin uses `van-ext` along with `mini-van-plate` so you can have everything ready from the start.
|
|
25
25
|
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
* In the near future we're going to have a `npm create-vanjs` CLI so stick around!
|
|
26
|
+
* Kickstart your VanJS project with `npm create vanjs@latest`. Some starter templates feature this plugin and most essential tools.
|
|
29
27
|
|
|
30
28
|
|
|
31
29
|
### Install
|
|
32
30
|
|
|
33
31
|
1) Install the plugin:
|
|
34
32
|
|
|
35
|
-
```bash
|
|
36
|
-
pnpm install vite-plugin-vanjs
|
|
37
|
-
```
|
|
38
|
-
|
|
39
33
|
```bash
|
|
40
34
|
npm install vite-plugin-vanjs
|
|
41
35
|
```
|
|
42
36
|
|
|
43
37
|
```bash
|
|
44
|
-
|
|
38
|
+
pnpm add vite-plugin-vanjs
|
|
45
39
|
```
|
|
46
40
|
|
|
47
41
|
```bash
|
|
48
|
-
|
|
42
|
+
deno add npm:vite-plugin-vanjs
|
|
49
43
|
```
|
|
50
44
|
|
|
51
45
|
```bash
|
|
52
|
-
|
|
46
|
+
bun install vite-plugin-vanjs
|
|
53
47
|
```
|
|
54
48
|
|
|
55
|
-
|
|
49
|
+
|
|
50
|
+
2) To add Typescript support, edit your `src/vite-env.d.ts` (or any global types you have set in your app) as follows:
|
|
56
51
|
|
|
57
52
|
```ts
|
|
58
53
|
/// <reference types="vite/client" />
|
|
@@ -62,7 +57,7 @@ yarn add vite-plugin-vanjs
|
|
|
62
57
|
|
|
63
58
|
### Usage
|
|
64
59
|
|
|
65
|
-
Update your `vite.config.
|
|
60
|
+
Update your `vite.config.ts` file:
|
|
66
61
|
```ts
|
|
67
62
|
// vite.config.mts
|
|
68
63
|
import { defineConfig } from 'vite';
|
|
@@ -84,7 +79,7 @@ import van from '@vanjs/van';
|
|
|
84
79
|
|
|
85
80
|
// use van as usual
|
|
86
81
|
const MyComponent = () => {
|
|
87
|
-
return van.div("Hello from VanJS!");
|
|
82
|
+
return van.tags.div("Hello from VanJS!");
|
|
88
83
|
};
|
|
89
84
|
```
|
|
90
85
|
Using `vanX` in your code:
|
|
@@ -112,17 +107,18 @@ const MyList = () => {
|
|
|
112
107
|
)
|
|
113
108
|
};
|
|
114
109
|
```
|
|
110
|
+
**Note**: Anywhere you have **vite-plugin-vanjs** enabled in your Vite apps, all imports from `"vanjs-core"` or `"vanjs-ext"` will be replaced with `"@vanjs/van"` and `"@vanjs/vanX"` respectivelly. In addition you have the `isServer` getter in the `@vanjs/setup` module, something you can use to exclude code execution in server/client environment.
|
|
115
111
|
|
|
116
112
|
|
|
117
113
|
### Router
|
|
118
|
-
The **vite-plugin-vanjs** provides a router with load and preload capability, code splitting and lazy loading, all via the exported `@vanjs/router` module. This functionality is still in early stages, but it manages to work with both Server Side Rendering (SSR) when using an appropriate starter template, as well as Client Side Rendering (CSR/SPA - your classic VanJS app), as we'll see in the example below.
|
|
114
|
+
The **vite-plugin-vanjs** plugin provides a router with load and preload capability, code splitting and lazy loading, all via the exported `@vanjs/router` module. This functionality is still in early stages, but it manages to work with both Server Side Rendering (SSR) when using an appropriate starter template, as well as Client Side Rendering (CSR/SPA - your classic VanJS app), as we'll see in the example below.
|
|
119
115
|
|
|
120
116
|
Here's a basic example, let's start with the `app.ts`:
|
|
121
117
|
|
|
122
118
|
```ts
|
|
123
119
|
// src/app.ts
|
|
124
120
|
import van from "vanjs-core";
|
|
125
|
-
import { Router, Route
|
|
121
|
+
import { Router, Route } from "@vanjs/router";
|
|
126
122
|
|
|
127
123
|
// define routes
|
|
128
124
|
Route({ path: '/', component: () => van.tags.div('Hello VanJS') });
|
|
@@ -142,7 +138,7 @@ Here's how a page should look like, pay attention to the comments:
|
|
|
142
138
|
```ts
|
|
143
139
|
// src/pages/about.ts
|
|
144
140
|
import van from "vanjs-core";
|
|
145
|
-
import { A } from "@vanjs/router";
|
|
141
|
+
import { A, navigate } from "@vanjs/router";
|
|
146
142
|
|
|
147
143
|
// define routes
|
|
148
144
|
export const route = {
|
|
@@ -160,29 +156,31 @@ export const route = {
|
|
|
160
156
|
// you must export your page component as either
|
|
161
157
|
// a named export "Page" or a default export
|
|
162
158
|
export function Page() {
|
|
163
|
-
const { div, h1, p,
|
|
159
|
+
const { div, h1, p, button } = van.tags;
|
|
164
160
|
return div(
|
|
165
161
|
h1('About'),
|
|
166
162
|
p('This is the about page'),
|
|
167
|
-
A({ href: "/" }, "Back to Home")
|
|
163
|
+
A({ href: "/" }, "Back to Home"),
|
|
164
|
+
button({ onclick: () => navigate('/about-details') }, "Learn more..")
|
|
168
165
|
)
|
|
169
166
|
}
|
|
170
167
|
```
|
|
171
168
|
**Notes**
|
|
172
169
|
- when hovering the `A` component, if it links to a lazy component it will trigger that page component preload, but not preload any data;
|
|
173
|
-
- if you use the regular `a` from `van.tags` instead of the `A` component, your application will work
|
|
170
|
+
- if you use the regular `a` from `van.tags` instead of the `A` component, your application will work just like a classic Multi-Page App (MPA);
|
|
171
|
+
- the `navigate` tool is used by the `A` component and you can also use it to navigate to different routes, something you can use with your API/logic.
|
|
174
172
|
|
|
175
173
|
|
|
176
174
|
### Metadata
|
|
177
|
-
The **vite-plugin-vanjs**
|
|
175
|
+
The **vite-plugin-vanjs** plugin provides metadata management via the exported `@vanjs/meta` module. This module works with both SSR and CSR, and makes it easy to work with.
|
|
178
176
|
|
|
179
177
|
Depending on the type of application, it's generally very easy to setup the system to work properly, we only need to make sure that we execute functions in a specific order:
|
|
180
178
|
|
|
181
|
-
* first we call the `initializeHeadTags` which allows the module to store the current tags that come from either a
|
|
179
|
+
* first we call the `initializeHeadTags` which allows the module to store the current tags that come from either a Vite starter template `index.html` or the server (SSR); if we don't call this function, the existing tags will be removed and some of them are very important (especially `charset` and `viewport`);
|
|
182
180
|
* then we define a set of default tags to be used by both client and server (if using an SSR template) on all pages that don't come with any metadata tags;
|
|
183
|
-
* lastly, on other pages, we define tags that override both the existing and the default tags
|
|
181
|
+
* lastly, on other pages, we define tags that override both the existing and the default tags.
|
|
184
182
|
|
|
185
|
-
|
|
183
|
+
Here's a quick example, first let's start again with the `app.ts`:
|
|
186
184
|
```ts
|
|
187
185
|
import van from 'vanjs-core'
|
|
188
186
|
import { Style, Title, Meta, initializeHeadTags } from '@vanjs/meta'
|
|
@@ -217,16 +215,16 @@ van.add(document.body, App());
|
|
|
217
215
|
```
|
|
218
216
|
**Note**
|
|
219
217
|
- the `Style` component doesn't have any unique attribute so we must use a unique ID to prevent duplicates;
|
|
220
|
-
- all provided metadata components don't return any markup, their function is to register new tags or update existing
|
|
218
|
+
- all provided metadata components don't return any markup, their function is to register new tags or update existing ones.
|
|
221
219
|
|
|
222
220
|
|
|
223
221
|
### JSX Transformation
|
|
224
|
-
|
|
225
|
-
To enable JSX transformation, you have to edit your `tsconfig.json` as follows:
|
|
222
|
+
To enable JSX transformation, you don't need to do anything except to add Typescript support if you need to. So edit your `tsconfig.json` as follows:
|
|
226
223
|
|
|
227
224
|
```json
|
|
228
225
|
{
|
|
229
226
|
"compilerOptions": {
|
|
227
|
+
/** other compilerOptions */
|
|
230
228
|
"jsx": "preserve",
|
|
231
229
|
"jsxImportSource": "@vanjs/jsx"
|
|
232
230
|
}
|
|
@@ -236,25 +234,25 @@ To enable JSX transformation, you have to edit your `tsconfig.json` as follows:
|
|
|
236
234
|
**Example**:
|
|
237
235
|
```tsx
|
|
238
236
|
// App.tsx
|
|
239
|
-
import type { ChildDom } from "vanjs-core";
|
|
240
237
|
import van from '@vanjs/van';
|
|
241
238
|
|
|
242
239
|
const App = () => {
|
|
243
240
|
const count = van.state(0);
|
|
241
|
+
const btnRef = van.state<{ current: HTMLElement }>();
|
|
244
242
|
|
|
245
243
|
return (
|
|
246
|
-
<button onClick={() => count.val++}>{count}</button>
|
|
244
|
+
<button ref={btnRef} onClick={() => count.val++}>{count}</button>
|
|
247
245
|
);
|
|
248
246
|
}
|
|
249
247
|
|
|
250
248
|
const root = document.getElementById("app") as HTMLElement;
|
|
251
249
|
|
|
252
|
-
van.add(root, <App />);
|
|
250
|
+
van.add(root, <App /> as HTMLElement);
|
|
253
251
|
```
|
|
254
252
|
|
|
255
253
|
**Notes**:
|
|
256
254
|
* in cases like this one, enforcing a certain typescript type via `as` might be in good order depending on who renders your component;
|
|
257
|
-
* you can use `ref` as a `van.state`, `class` instead of `className`, `for` instead of `htmlFor`;
|
|
255
|
+
* you can use `ref` as a `van.state`, `class` attribute instead of `className`, `for` attribute instead of `htmlFor`;
|
|
258
256
|
* you can use style as both an object and a string;
|
|
259
257
|
* for a JSX starter template, check out the [vite-starter-vanjs-ssr-jsx](https://github.com/thednp/vite-starter-vanjs-ssr-jsx).
|
|
260
258
|
* for a pure vanilla starter template, check out the [vite-starter-vanjs-ssr](https://github.com/thednp/vite-starter-vanjs-ssr).
|
package/client/global.d.ts
CHANGED
|
@@ -36,6 +36,10 @@ declare module "@vanjs/client" {
|
|
|
36
36
|
*/
|
|
37
37
|
export const hydrate: (
|
|
38
38
|
target: HTMLElement,
|
|
39
|
-
content:
|
|
39
|
+
content:
|
|
40
|
+
| ChildElement
|
|
41
|
+
| ChildElement[]
|
|
42
|
+
| JSX.Element
|
|
43
|
+
| Promise<ChildElement | ChildElement[] | JSX.Element>,
|
|
40
44
|
) => HTMLElement;
|
|
41
45
|
}
|
package/client/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { unwrap } from "
|
|
1
|
+
import { unwrap } from "../router/index.mjs";
|
|
2
|
+
import { getTagKey } from "../meta/helpers.mjs";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* @param {Element} element
|
|
@@ -37,12 +38,105 @@ export const styleToString = (style) => {
|
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* @param {Element} target the root element
|
|
40
|
-
* @param {Element | Element[]} content the element(s) to hydrate
|
|
41
|
+
* @param {Element | Element[] | Promise<Element | Element[]>} content the element(s) to hydrate
|
|
41
42
|
*/
|
|
42
43
|
export const hydrate = (target, content) => {
|
|
44
|
+
if (content instanceof Promise) {
|
|
45
|
+
content.then((res) => {
|
|
46
|
+
const wrapper = unwrap(res);
|
|
47
|
+
target.replaceChildren(
|
|
48
|
+
...(Array.from(wrapper.children)),
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
return target;
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
const wrapper = unwrap(content);
|
|
44
|
-
target.
|
|
45
|
-
|
|
46
|
-
)
|
|
55
|
+
const currentChildren = Array.from(target.children);
|
|
56
|
+
const newChildren = Array.from(wrapper.children);
|
|
57
|
+
const isStyleLink = (tag) =>
|
|
58
|
+
[HTMLStyleElement, HTMLLinkElement].some((e) => tag instanceof e);
|
|
59
|
+
const isStyle = (tag) => tag instanceof HTMLStyleElement;
|
|
60
|
+
const isLink = (tag) => tag instanceof HTMLLinkElement;
|
|
61
|
+
|
|
62
|
+
if (target.tagName.toLowerCase() === "head") {
|
|
63
|
+
// Handle non-style/link tags first
|
|
64
|
+
const regularTags = newChildren.filter((child) => !isStyleLink(child));
|
|
65
|
+
|
|
66
|
+
// Handle style/link tags separately
|
|
67
|
+
const styleTags = newChildren.filter((child) => isStyleLink(child));
|
|
68
|
+
|
|
69
|
+
// Create maps for existing tags
|
|
70
|
+
const existingStyles = new Map(
|
|
71
|
+
currentChildren.filter(isStyleLink)
|
|
72
|
+
.map((child) => [getTagKey(child), child]),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Process regular tags normally
|
|
76
|
+
regularTags.forEach((newChild) => {
|
|
77
|
+
const key = getTagKey(newChild);
|
|
78
|
+
const existing = currentChildren.find((child) =>
|
|
79
|
+
getTagKey(child) === key
|
|
80
|
+
);
|
|
81
|
+
if (existing) {
|
|
82
|
+
existing.replaceWith(newChild);
|
|
83
|
+
} else {
|
|
84
|
+
target.appendChild(newChild);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Process style tags with special handling
|
|
89
|
+
styleTags.forEach((newChild) => {
|
|
90
|
+
const key = getTagKey(newChild);
|
|
91
|
+
const existing = existingStyles.get(key);
|
|
92
|
+
|
|
93
|
+
// Skip if tag already exists with same content+id/href
|
|
94
|
+
if (existing) {
|
|
95
|
+
/* istanbul ignore next - try again later */
|
|
96
|
+
if (isStyle(existing) && isStyle(newChild)) {
|
|
97
|
+
if (
|
|
98
|
+
existing.textContent === newChild.textContent &&
|
|
99
|
+
existing.id === newChild.id
|
|
100
|
+
) return;
|
|
101
|
+
}
|
|
102
|
+
/* istanbul ignore next - try again later */
|
|
103
|
+
if (isLink(existing) && isLink(newChild)) {
|
|
104
|
+
if (existing.href === newChild.href) return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// For link tags, add with disabled state first
|
|
109
|
+
if (isLink(newChild)) {
|
|
110
|
+
const temp = newChild.cloneNode();
|
|
111
|
+
temp.disabled = true;
|
|
112
|
+
|
|
113
|
+
const originalRel = temp.rel;
|
|
114
|
+
temp.rel = "preload";
|
|
115
|
+
temp.as = "style";
|
|
116
|
+
/* istanbul ignore next */
|
|
117
|
+
temp.onload = () => {
|
|
118
|
+
temp.rel = originalRel;
|
|
119
|
+
temp.removeAttribute("as");
|
|
120
|
+
temp.disabled = false;
|
|
121
|
+
if (existing && existing.parentNode === target) {
|
|
122
|
+
existing.remove();
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
target.appendChild(temp);
|
|
127
|
+
} // For style tags, add new one first
|
|
128
|
+
/* istanbul ignore if - try again later */ else if (isStyle(newChild)) {
|
|
129
|
+
target.appendChild(newChild);
|
|
130
|
+
/* istanbul ignore next - try again later */
|
|
131
|
+
if (existing && existing.parentNode === target) {
|
|
132
|
+
// Remove old one in next frame
|
|
133
|
+
requestAnimationFrame(() => existing.remove());
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
target.replaceChildren(...newChildren);
|
|
139
|
+
}
|
|
140
|
+
|
|
47
141
|
return target;
|
|
48
142
|
};
|
package/client/types.d.ts
CHANGED
|
@@ -30,5 +30,9 @@ export const styleToString: (source: string | CSS.Properties) => string;
|
|
|
30
30
|
*/
|
|
31
31
|
export const hydrate: (
|
|
32
32
|
target: HTMLElement,
|
|
33
|
-
content:
|
|
33
|
+
content:
|
|
34
|
+
| HTMLElement
|
|
35
|
+
| HTMLElement[]
|
|
36
|
+
| JSX.Element
|
|
37
|
+
| Promise<HTMLElement | HTMLElement[] | JSX.Element>,
|
|
34
38
|
) => HTMLElement;
|
package/jsx/global.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
declare module "@vanjs/jsx" {
|
|
2
2
|
import type { ChildDom, Primitive } from "vanjs-core";
|
|
3
|
-
import type { Element as
|
|
3
|
+
import type { Element as VElement } from "mini-van-plate/van-plate";
|
|
4
4
|
export const Fragment = ({ children }: { children?: JSX.Element }) =>
|
|
5
5
|
JSX.Element;
|
|
6
6
|
// export type VanElement = Element;
|
|
7
7
|
export type VanNode =
|
|
8
8
|
| Primitive
|
|
9
9
|
| ChildDom
|
|
10
|
-
|
|
|
10
|
+
| VElement
|
|
11
11
|
| VanNode[]
|
|
12
12
|
| (() => VanNode)
|
|
13
|
+
| undefined
|
|
13
14
|
| null;
|
|
14
15
|
|
|
15
16
|
export function jsx(
|
package/jsx/jsx.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// deno-lint-ignore-file no-empty-interface ban-types
|
|
2
2
|
|
|
3
3
|
import * as csstype from "csstype";
|
|
4
|
-
import type {
|
|
4
|
+
import type { Primitive, State, StateView } from "vanjs-core";
|
|
5
|
+
import { Element as VElement } from "mini-van-plate/van-plate";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Based on JSX types for Surplus and Inferno and adapted for `dom-expressions`.
|
|
@@ -9,8 +10,17 @@ import type { ChildDom, State } from "vanjs-core";
|
|
|
9
10
|
* https://github.com/adamhaile/surplus/blob/master/index.d.ts
|
|
10
11
|
* https://github.com/infernojs/inferno/blob/master/packages/inferno/src/core/types.ts
|
|
11
12
|
*/
|
|
12
|
-
type DOMElement = Element;
|
|
13
|
-
|
|
13
|
+
type DOMElement = globalThis.Element;
|
|
14
|
+
type PrimitiveChild = Primitive | State<Primitive | null | undefined>;
|
|
15
|
+
type VanElement = SVGElement | HTMLElement | DOMElement | Node | VElement;
|
|
16
|
+
export type VanNode =
|
|
17
|
+
| VanElement
|
|
18
|
+
| PrimitiveChild
|
|
19
|
+
| VanNode[]
|
|
20
|
+
| (() => VanNode)
|
|
21
|
+
| null
|
|
22
|
+
| undefined;
|
|
23
|
+
|
|
14
24
|
export type { Fragment } from "./fragment";
|
|
15
25
|
|
|
16
26
|
export as namespace JSX;
|
|
@@ -18,18 +28,34 @@ export = JSX;
|
|
|
18
28
|
|
|
19
29
|
declare namespace JSX {
|
|
20
30
|
// type FunctionMaybe<T = unknown> = { (): T } | T;
|
|
21
|
-
type
|
|
31
|
+
// type Element = VanNode;
|
|
32
|
+
type FunctionMaybe<T = unknown> = (() => T) | StateView<T> | T;
|
|
22
33
|
type Element =
|
|
23
|
-
|
|
|
34
|
+
| State<Primitive | null | undefined>
|
|
24
35
|
| Node
|
|
25
36
|
| DOMElement
|
|
37
|
+
| HTMLElement
|
|
26
38
|
| ArrayElement
|
|
39
|
+
// | TagComponent<any>
|
|
40
|
+
// | Component
|
|
27
41
|
| FunctionElement
|
|
28
42
|
| (string & {})
|
|
29
|
-
|
|
|
30
|
-
| boolean
|
|
43
|
+
| Primitive
|
|
31
44
|
| null
|
|
32
45
|
| undefined;
|
|
46
|
+
|
|
47
|
+
type ComponentProps<K> = Omit<IntrinsicElements[K], "children">;
|
|
48
|
+
type Component<
|
|
49
|
+
K extends keyof IntrinsicElements,
|
|
50
|
+
O extends (Record<string, PropValueOrDerived> | undefined) = undefined,
|
|
51
|
+
> = (
|
|
52
|
+
props?:
|
|
53
|
+
& (O extends object ? ComponentProps<K> & Partial<O> : ComponentProps<K>)
|
|
54
|
+
& {
|
|
55
|
+
children?: Element;
|
|
56
|
+
},
|
|
57
|
+
) => HTMLElementTagNameMap[T];
|
|
58
|
+
|
|
33
59
|
interface ArrayElement extends Array<Element> {}
|
|
34
60
|
interface FunctionElement {
|
|
35
61
|
(): Element;
|
|
@@ -88,11 +114,18 @@ declare namespace JSX {
|
|
|
88
114
|
|
|
89
115
|
interface IntrinsicAttributes {
|
|
90
116
|
// ref?: unknown | ((e: unknown) => void);
|
|
91
|
-
ref?: State<T>;
|
|
117
|
+
// ref?: State<T>;
|
|
118
|
+
// ref?: Element;
|
|
119
|
+
// ref?: State<Element> & State<{ current?: Element }>;
|
|
120
|
+
ref?: State<{ current?: Element }>;
|
|
92
121
|
}
|
|
93
122
|
interface CustomAttributes<T> {
|
|
94
123
|
// ref?: State<T> | T | ((el: T) => void);
|
|
95
|
-
ref?: State<T>;
|
|
124
|
+
// ref?: State<T>;
|
|
125
|
+
// ref?: T;
|
|
126
|
+
// ref?: { current: State<T> };
|
|
127
|
+
// ref?: State<T> & State<{ current: T }>;
|
|
128
|
+
ref?: State<{ current: T }>;
|
|
96
129
|
}
|
|
97
130
|
interface ExplicitProperties {}
|
|
98
131
|
interface ExplicitAttributes {}
|
package/jsx/jsx.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import van from "
|
|
2
|
-
import setup from "
|
|
3
|
-
import { setAttribute, styleToString } from "
|
|
1
|
+
import van from "../setup/van.mjs";
|
|
2
|
+
import setup from "../setup/index.mjs";
|
|
3
|
+
import { setAttribute, styleToString } from "../client/index.mjs";
|
|
4
4
|
|
|
5
5
|
export const jsx = (jsxTag, { children, ref, style, ...props }) => {
|
|
6
6
|
if (typeof jsxTag === "string") {
|
|
@@ -29,15 +29,15 @@ export const jsx = (jsxTag, { children, ref, style, ...props }) => {
|
|
|
29
29
|
setAttribute(newElement, k, value);
|
|
30
30
|
}
|
|
31
31
|
/* istanbul ignore else */
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
newElement.style.cssText = styleToString(style);
|
|
32
|
+
van.derive(() => {
|
|
33
|
+
if (style) {
|
|
34
|
+
const styleProp = typeof style === "function" ? style() : style;
|
|
35
|
+
newElement.style.cssText = styleToString(styleProp);
|
|
37
36
|
}
|
|
38
|
-
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (ref) ref.val = { current: newElement };
|
|
39
40
|
|
|
40
|
-
if (ref) ref.val = newElement;
|
|
41
41
|
return newElement;
|
|
42
42
|
}
|
|
43
43
|
|
package/meta/Head.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import setup from "
|
|
1
|
+
import setup from "../setup/index.mjs";
|
|
2
2
|
import { getTagKey } from "./helpers.mjs";
|
|
3
3
|
|
|
4
4
|
/** @typedef {typeof import("./types.d.ts").getHeadTags} GetTags */
|
|
5
5
|
/** @typedef {typeof import("./types.d.ts").createHeadTags} CreateTags */
|
|
6
6
|
/** @typedef {typeof import("./types.d.ts").resetHeadTags} ResetTags */
|
|
7
7
|
/** @typedef {typeof import("./types.d.ts").initializeHeadTags} InitializeTags */
|
|
8
|
-
/** @typedef {import("./types.d.ts").
|
|
8
|
+
/** @typedef {typeof import("./types.d.ts").addMeta} AddMeta */
|
|
9
9
|
/** @typedef {typeof import("./types.d.ts").Head} HeadComp */
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -52,7 +52,7 @@ export const initializeHeadTags = () => {
|
|
|
52
52
|
const tags = getHeadTags();
|
|
53
53
|
/* istanbul ignore else */
|
|
54
54
|
if (!tags.size && !setup.isServer) {
|
|
55
|
-
|
|
55
|
+
Array.from(document.head.children).forEach((tag) => {
|
|
56
56
|
tags.set(getTagKey(tag), tag);
|
|
57
57
|
});
|
|
58
58
|
}
|
package/meta/global.d.ts
CHANGED
|
@@ -13,8 +13,10 @@ declare module "@vanjs/meta" {
|
|
|
13
13
|
string,
|
|
14
14
|
SupportedTags | TagFunc
|
|
15
15
|
>;
|
|
16
|
-
export
|
|
17
|
-
export
|
|
16
|
+
export const resetHeadTags: () => void;
|
|
17
|
+
export const initializeHeadTags: (
|
|
18
|
+
_html?: string,
|
|
19
|
+
) => void;
|
|
18
20
|
|
|
19
21
|
export type SupportedTags =
|
|
20
22
|
| HTMLTitleElement
|
|
@@ -27,34 +29,44 @@ declare module "@vanjs/meta" {
|
|
|
27
29
|
|
|
28
30
|
export type HeadTags = SupportedTags[] | TagFunc[];
|
|
29
31
|
|
|
30
|
-
export
|
|
32
|
+
export const addMeta: (tag?: TagProps) => void;
|
|
33
|
+
|
|
34
|
+
export const Head: () => HeadTags;
|
|
31
35
|
|
|
32
|
-
// export declare const Head: () => () => TagFunc[];
|
|
33
|
-
export declare const Head: () => () => SupportedTags[];
|
|
34
36
|
export const Title: (
|
|
35
37
|
props: PropsWithKnownKeys<HTMLTitleElement>,
|
|
36
38
|
content?: string,
|
|
37
39
|
) => null;
|
|
38
|
-
|
|
40
|
+
|
|
41
|
+
export const Meta: (
|
|
42
|
+
props: PropsWithKnownKeys<HTMLMetaElement> & { charset?: string & "utf-8" },
|
|
43
|
+
) => null;
|
|
44
|
+
|
|
39
45
|
export const Style: (
|
|
40
46
|
props: PropsWithKnownKeys<HTMLStyleElement>,
|
|
41
47
|
content?: string,
|
|
42
48
|
) => null;
|
|
49
|
+
|
|
43
50
|
export const Link: (props: PropsWithKnownKeys<HTMLLinkElement>) => null;
|
|
51
|
+
|
|
44
52
|
export const Script: (
|
|
45
53
|
props: PropsWithKnownKeys<HTMLScriptElement>,
|
|
46
54
|
content?: string,
|
|
47
55
|
) => null;
|
|
48
56
|
|
|
49
|
-
export
|
|
57
|
+
export const parseAttributes: (
|
|
50
58
|
attributeString: string,
|
|
51
59
|
) => Record<string, string>;
|
|
52
60
|
|
|
53
|
-
export
|
|
61
|
+
export const getTagAttribute: (tag: TagProps) => string;
|
|
54
62
|
|
|
55
|
-
export
|
|
63
|
+
export const getTagKey: (tag: TagProps) => string;
|
|
56
64
|
|
|
57
|
-
export const
|
|
58
|
-
|
|
59
|
-
|
|
65
|
+
export const extractTags: (
|
|
66
|
+
html?: string,
|
|
67
|
+
) => {
|
|
68
|
+
tag: TagFunc;
|
|
69
|
+
props: PropsWithKnownKeys<SupportedTags>;
|
|
70
|
+
children: TagFunc[];
|
|
71
|
+
}[];
|
|
60
72
|
}
|
package/meta/helpers.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import setup from "
|
|
1
|
+
import setup from "../setup/index.mjs";
|
|
2
|
+
// import { getAttributes } from "@thednp/domparser/parser";
|
|
2
3
|
|
|
3
|
-
/** @type {import('./types.d.ts').
|
|
4
|
+
/** @type {typeof import('./types.d.ts').parseAttributes} */
|
|
4
5
|
export const parseAttributes = (attributeString) => {
|
|
5
6
|
/** @type {Record<string, string>} */
|
|
6
7
|
const attributes = {};
|
|
@@ -39,10 +40,11 @@ const getTagAttribute = (tag) => {
|
|
|
39
40
|
return "";
|
|
40
41
|
};
|
|
41
42
|
|
|
42
|
-
/** @type {import('./types.d.ts').
|
|
43
|
+
/** @type {typeof import('./types.d.ts').getTagKey} */
|
|
43
44
|
export const getTagKey = (tag) => {
|
|
44
45
|
const normalizedTag = setup.isServer
|
|
45
46
|
? { tagName: tag.name.toUpperCase(), ...parseAttributes(tag.propsStr) }
|
|
47
|
+
// ? { tagName: tag.name.toUpperCase(), ...getAttributes(tag.propsStr) }
|
|
46
48
|
: tag;
|
|
47
49
|
|
|
48
50
|
return normalizedTag.tagName +
|
package/meta/tags.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { addMeta } from "./Head.mjs";
|
|
|
5
5
|
/** @typedef {import("./types.d.ts").TagProps} TagProps */
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Add a new title tag
|
|
8
|
+
* Add a new `<title>` tag
|
|
9
9
|
* @type {(props: PropsWithKnownKeys<HTMLTitleElement>, content?: string) => null}
|
|
10
10
|
*/
|
|
11
11
|
export const Title = (props, content) => {
|
|
@@ -15,7 +15,7 @@ export const Title = (props, content) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Add a new meta tag
|
|
18
|
+
* Add a new `<meta>` tag
|
|
19
19
|
* @type {(props: PropsWithKnownKeys<HTMLMetaElement>) => null}
|
|
20
20
|
*/
|
|
21
21
|
export const Meta = (props) => {
|
|
@@ -25,7 +25,7 @@ export const Meta = (props) => {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Add a new link tag
|
|
28
|
+
* Add a new `<link>` tag
|
|
29
29
|
* @type {(props: PropsWithKnownKeys<HTMLLinkElement>) => null}
|
|
30
30
|
*/
|
|
31
31
|
export const Link = (props) => {
|
|
@@ -35,19 +35,17 @@ export const Link = (props) => {
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* Add a new script tag
|
|
38
|
+
* Add a new `<script>` tag
|
|
39
39
|
* @type {(props: PropsWithKnownKeys<HTMLScriptElement>, content?: string) => null}
|
|
40
40
|
*/
|
|
41
41
|
export const Script = (props, content) => {
|
|
42
42
|
const { script } = van.tags;
|
|
43
|
-
// const realContent = content ? content.toString() : props;
|
|
44
|
-
// const realProps = content ? props : props;
|
|
45
43
|
addMeta(script(props, content));
|
|
46
44
|
return null;
|
|
47
45
|
};
|
|
48
46
|
|
|
49
47
|
/**
|
|
50
|
-
* Add a new style tag
|
|
48
|
+
* Add a new `<style>` tag
|
|
51
49
|
* @type {(props: PropsWithKnownKeys<HTMLStyleElement>, content: string) => null}
|
|
52
50
|
*/
|
|
53
51
|
export const Style = (props, content) => {
|