vite-plugin-vanjs 0.0.3 → 0.0.5
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 +143 -15
- package/client/global.d.ts +41 -0
- package/client/index.mjs +48 -0
- package/client/package.json +18 -0
- package/client/types.d.ts +34 -0
- package/jsx/global.d.ts +4 -3
- package/jsx/jsx.d.ts +18 -10
- package/jsx/jsx.mjs +3 -2
- package/jsx/package.json +1 -1
- package/jsx/types.d.ts +16 -0
- package/meta/Head.mjs +81 -0
- package/meta/global.d.ts +60 -0
- package/meta/helpers.mjs +52 -0
- package/meta/index.mjs +3 -0
- package/meta/package.json +18 -0
- package/meta/tags.mjs +57 -0
- package/meta/types.d.ts +36 -0
- package/package.json +45 -13
- package/router/a.mjs +50 -0
- package/router/cache.mjs +14 -0
- package/router/global.d.ts +162 -0
- package/router/helpers.mjs +198 -0
- package/router/index.mjs +7 -0
- package/router/lazy.mjs +60 -0
- package/router/package.json +19 -0
- package/router/router.mjs +43 -0
- package/router/routes.mjs +51 -0
- package/router/state.mjs +27 -0
- package/router/types.d.ts +156 -0
- package/server/global.d.ts +49 -0
- package/server/index.mjs +97 -0
- package/server/package.json +20 -0
- package/server/types.d.ts +38 -0
- package/setup/package.json +2 -2
- package/setup/van.d.ts +1 -0
- package/setup/vanX.d.ts +1 -0
- package/setup/vanX.mjs +1 -1
- package/src/index.mjs +10 -10
- package/src/types.d.ts +28 -4
- package/tsconfig.json +14 -2
- package/jsx/index.d.ts +0 -16
- package/jsx/utils.mjs +0 -24
- /package/setup/{index.d.ts → types.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
## vite-plugin-vanjs
|
|
2
2
|
|
|
3
|
+
[](https://coveralls.io/github/thednp/vite-plugin-vanjs)
|
|
4
|
+
[](https://github.com/thednp/vite-plugin-vanjs/actions/workflows/ci.yml)
|
|
3
5
|
[](https://www.npmjs.com/package/vite-plugin-vanjs)
|
|
4
6
|
[](http://npm-stat.com/charts.html?package=vite-plugin-vanjs)
|
|
5
7
|
[](https://www.typescriptlang.org/)
|
|
6
|
-
[](https://github.com/vanjs-org/van)
|
|
9
|
+
[](https://github.com/vanjs-org/mini-van-plate)
|
|
10
|
+
[](https://www.vitest.dev/)
|
|
11
|
+
[](https://vite.dev)
|
|
9
12
|
|
|
10
|
-
A
|
|
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, this one allows you to split code and lazy load components with ease, handles both Client Side Rendering (SSR) and Server Side Rendering (CSR) and makes it really easy to work with;
|
|
15
|
+
* ***@vanjs/meta*** - allows you to create metadata for your pages as well as load additional assets with ease;
|
|
16
|
+
* ***@vanjs/jsx*** - enables JSX transformation;
|
|
17
|
+
* ***@vanjs/setup*** - enables loading VanJS modules isomorphically;
|
|
18
|
+
* ***@vanjs/server*** - provides various tools for Server Side Rendering;
|
|
19
|
+
* ***@vanjs/client*** - provides various tools for Client Side Rendering.
|
|
11
20
|
|
|
12
|
-
The plugin
|
|
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.
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
### Notes
|
|
24
|
+
* The plugin uses `van-ext` along with `mini-van-plate` so you can have everything ready from start.
|
|
25
|
+
|
|
26
|
+
* The recommended starter templates for you are the [vite-starter-vanjs-ssr](https://github.com/thednp/vite-starter-vanjs-ssr) and [vite-starter-vanjs-ssr-jsx](https://github.com/thednp/vite-starter-vanjs-ssr-jsx) which already include this plugin.
|
|
27
|
+
|
|
28
|
+
* In the near future we're going to have a `npm create-vanjs` CLI so stick around!
|
|
15
29
|
|
|
16
30
|
|
|
17
31
|
### Install
|
|
@@ -19,7 +33,7 @@ The recommended starter templates for you are the [vite-starter-vanjs-ssr](https
|
|
|
19
33
|
1) Install the plugin:
|
|
20
34
|
|
|
21
35
|
```bash
|
|
22
|
-
pnpm
|
|
36
|
+
pnpm install vite-plugin-vanjs
|
|
23
37
|
```
|
|
24
38
|
|
|
25
39
|
```bash
|
|
@@ -27,10 +41,18 @@ npm install vite-plugin-vanjs
|
|
|
27
41
|
```
|
|
28
42
|
|
|
29
43
|
```bash
|
|
30
|
-
deno
|
|
44
|
+
deno install npm:vite-plugin-vanjs
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
bun add vite-plugin-vanjs
|
|
31
49
|
```
|
|
32
50
|
|
|
33
|
-
|
|
51
|
+
```bash
|
|
52
|
+
yarn add vite-plugin-vanjs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2) To add typescript support, edit your `src/vite-env.d.ts` (or any global types you have set in your app) as follows:
|
|
34
56
|
|
|
35
57
|
```ts
|
|
36
58
|
/// <reference types="vite/client" />
|
|
@@ -54,7 +76,7 @@ export default defineConfig({
|
|
|
54
76
|
|
|
55
77
|
**Example**:
|
|
56
78
|
|
|
57
|
-
While the plugin will resolve the appropriate modules depending on the environment, for your convenience, you can also import the `@vanjs/van` and `@vanjs/vanX` virtual modules, so the plugin makes sure to load the right modules where needed.
|
|
79
|
+
While the plugin will resolve the appropriate modules automatically depending on the environment, for your convenience, you can also import the `@vanjs/van` and `@vanjs/vanX` virtual modules, so the plugin makes sure to load the right modules where needed.
|
|
58
80
|
|
|
59
81
|
```ts
|
|
60
82
|
// my-component.ts
|
|
@@ -65,7 +87,7 @@ const MyComponent = () => {
|
|
|
65
87
|
return van.div("Hello from VanJS!");
|
|
66
88
|
};
|
|
67
89
|
```
|
|
68
|
-
|
|
90
|
+
Using `vanX` in your code:
|
|
69
91
|
|
|
70
92
|
```ts
|
|
71
93
|
// my-list.ts
|
|
@@ -92,6 +114,112 @@ const MyList = () => {
|
|
|
92
114
|
```
|
|
93
115
|
|
|
94
116
|
|
|
117
|
+
### 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.
|
|
119
|
+
|
|
120
|
+
Here's a basic example, let's start with the `app.ts`:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// src/app.ts
|
|
124
|
+
import van from "vanjs-core";
|
|
125
|
+
import { Router, Route, A } from "@vanjs/router";
|
|
126
|
+
|
|
127
|
+
// define routes
|
|
128
|
+
Route({ path: '/', component: () => van.tags.div('Hello VanJS') });
|
|
129
|
+
Route({ path: '/about', component: lazy(() => import('./pages/about'))});
|
|
130
|
+
Route({ path: '*', component: () => van.tags.div('404 - Page Not Found') });
|
|
131
|
+
|
|
132
|
+
function App() {
|
|
133
|
+
// the Router is only an outlet
|
|
134
|
+
export default Route();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// render or hydrate the app
|
|
138
|
+
van.add(document.body, App());
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Here's how a page should look like, pay attention to the comments:
|
|
142
|
+
```ts
|
|
143
|
+
// src/pages/about.ts
|
|
144
|
+
import van from "vanjs-core";
|
|
145
|
+
import { A } from "@vanjs/router";
|
|
146
|
+
|
|
147
|
+
// define routes
|
|
148
|
+
export const route = {
|
|
149
|
+
preload: async () => {
|
|
150
|
+
// in most cases you may want to enforce user access control
|
|
151
|
+
console.log('About preload triggered');
|
|
152
|
+
},
|
|
153
|
+
load: async () => {
|
|
154
|
+
// Load data if needed
|
|
155
|
+
// you might want to cache this data
|
|
156
|
+
console.log('About load triggered');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// you must export your page component as either
|
|
161
|
+
// a named export "Page" or a default export
|
|
162
|
+
export function Page() {
|
|
163
|
+
const { div, h1, p, br } = van.tags;
|
|
164
|
+
return div(
|
|
165
|
+
h1('About'),
|
|
166
|
+
p('This is the about page'),
|
|
167
|
+
A({ href: "/" }, "Back to Home")
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
**Notes**
|
|
172
|
+
- 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 as a classic Multi-Page App (MPA).
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
### Metadata
|
|
177
|
+
The **vite-plugin-vanjs** also 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
|
+
|
|
179
|
+
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
|
+
|
|
181
|
+
* 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 important (especially `charset` and `viewport`);
|
|
182
|
+
* 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
|
|
184
|
+
|
|
185
|
+
Ok let's start again with the `app.ts`:
|
|
186
|
+
```ts
|
|
187
|
+
import van from 'vanjs-core'
|
|
188
|
+
import { Style, Title, Meta, initializeHeadTags } from '@vanjs/meta'
|
|
189
|
+
|
|
190
|
+
function App() {
|
|
191
|
+
const { div, h1, p } van.tags;
|
|
192
|
+
|
|
193
|
+
// when app is first time executed
|
|
194
|
+
// we need to register tags coming
|
|
195
|
+
// from the index.html template
|
|
196
|
+
initializeHeadTags();
|
|
197
|
+
|
|
198
|
+
// a good practice is to define some default tags
|
|
199
|
+
// they are used on pages where no tags are set
|
|
200
|
+
Title("VanJS + Vite App");
|
|
201
|
+
Meta({ name: "description", content: "Sample app description" });
|
|
202
|
+
Meta({ property: "og:description", content: "Some open graph description for your app" });
|
|
203
|
+
Link({ href: 'path-to/your-style.css', rel: "stylesheet" });
|
|
204
|
+
Script({ src: 'path-to/your-script.js' });
|
|
205
|
+
Style({ id: "app-style" },
|
|
206
|
+
`p { margin-bottom: 1rem }`
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
return div(
|
|
210
|
+
h1('Hello VanJS!'),
|
|
211
|
+
p('Sample paragraph.')
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// render or hydrate the app
|
|
216
|
+
van.add(document.body, App());
|
|
217
|
+
```
|
|
218
|
+
**Note**
|
|
219
|
+
- 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 tags.
|
|
221
|
+
|
|
222
|
+
|
|
95
223
|
### JSX Transformation
|
|
96
224
|
|
|
97
225
|
To enable JSX transformation, you have to edit your `tsconfig.json` as follows:
|
|
@@ -119,24 +247,24 @@ const App = () => {
|
|
|
119
247
|
);
|
|
120
248
|
}
|
|
121
249
|
|
|
122
|
-
|
|
250
|
+
const root = document.getElementById("app") as HTMLElement;
|
|
123
251
|
|
|
252
|
+
van.add(root, <App />);
|
|
124
253
|
```
|
|
125
254
|
|
|
126
255
|
**Notes**:
|
|
127
|
-
* in
|
|
256
|
+
* in cases like this one, enforcing a certain typescript type via `as` might be in good order depending on who renders your component;
|
|
128
257
|
* you can use `ref` as a `van.state`, `class` instead of `className`, `for` instead of `htmlFor`;
|
|
129
258
|
* you can use style as both an object and a string;
|
|
130
259
|
* for a JSX starter template, check out the [vite-starter-vanjs-ssr-jsx](https://github.com/thednp/vite-starter-vanjs-ssr-jsx).
|
|
131
260
|
* for a pure vanilla starter template, check out the [vite-starter-vanjs-ssr](https://github.com/thednp/vite-starter-vanjs-ssr).
|
|
132
261
|
|
|
133
262
|
|
|
134
|
-
|
|
135
263
|
### Credits
|
|
136
264
|
* [van-jsx](https://github.com/herudi/van-jsx) a simple Vanilla JSX implementation;
|
|
137
265
|
* [vanjs-jsx](https://github.com/vanjs-org/van/tree/main/addons/van_jsx) the official VanJS addon;
|
|
138
266
|
* [surplus](https://github.com/adamhaile/surplus/blob/master/index.d.ts) for Typescript definitions also used by SolidJS;
|
|
139
|
-
* [inferno](https://github.com/infernojs/inferno/blob/master/packages/inferno/src/core/types.ts) also typescript definitions.
|
|
267
|
+
* [inferno](https://github.com/infernojs/inferno/blob/master/packages/inferno/src/core/types.ts) also for typescript definitions.
|
|
140
268
|
|
|
141
269
|
|
|
142
270
|
### License
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
declare module "@vanjs/client" {
|
|
2
|
+
import * as CSS from "csstype";
|
|
3
|
+
import type {
|
|
4
|
+
Element as VanElement,
|
|
5
|
+
TagFunc,
|
|
6
|
+
} from "mini-van-plate/van-plate";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Sets the attribute value of the given name of the given element.
|
|
10
|
+
*
|
|
11
|
+
* @param element the target element
|
|
12
|
+
* @param key the attribute name
|
|
13
|
+
* @param value the attribute value
|
|
14
|
+
*/
|
|
15
|
+
export const setAttribute: (
|
|
16
|
+
element: Element,
|
|
17
|
+
name: string,
|
|
18
|
+
value: boolean | string | number | null | undefined,
|
|
19
|
+
) => void;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Normalize the style value and convert it to a string
|
|
23
|
+
*
|
|
24
|
+
* @param source the style value
|
|
25
|
+
* @returns the normalized style string
|
|
26
|
+
*/
|
|
27
|
+
export const styleToString: (source: string | CSS.Properties) => string;
|
|
28
|
+
|
|
29
|
+
type ChildElement = TagFunc | VanElement | HTMLElement | SVGElement;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Hydrate the target element with the given content(s).
|
|
33
|
+
*
|
|
34
|
+
* @param target the target element
|
|
35
|
+
* @param content the element(s) to hydrate
|
|
36
|
+
*/
|
|
37
|
+
export const hydrate: (
|
|
38
|
+
target: HTMLElement,
|
|
39
|
+
content: ChildElement | ChildElement[],
|
|
40
|
+
) => HTMLElement;
|
|
41
|
+
}
|
package/client/index.mjs
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { unwrap } from "@vanjs/router";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {Element} element
|
|
5
|
+
* @param {string} key
|
|
6
|
+
* @param {boolean | string | number | null | undefined} value
|
|
7
|
+
*/
|
|
8
|
+
export const setAttribute = (element, key, value) => {
|
|
9
|
+
if (value == null || value === false || value === "" || value === undefined) {
|
|
10
|
+
element.removeAttribute(key);
|
|
11
|
+
} else {
|
|
12
|
+
const attr = value === true ? "" : String(value);
|
|
13
|
+
element.setAttribute(key, attr);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {import("csstype").Properties | string} style
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
export const styleToString = (style) => {
|
|
22
|
+
return typeof style === "string"
|
|
23
|
+
? style
|
|
24
|
+
: typeof style === "object"
|
|
25
|
+
? Object.entries(style).reduce((acc, [key, value]) =>
|
|
26
|
+
acc +
|
|
27
|
+
key
|
|
28
|
+
.split(/(?=[A-Z])/)
|
|
29
|
+
.join("-")
|
|
30
|
+
.toLowerCase() +
|
|
31
|
+
":" +
|
|
32
|
+
// allow state values in style object
|
|
33
|
+
(typeof value === "object" && "val" in value ? value.val : value) +
|
|
34
|
+
";", "")
|
|
35
|
+
: /* istanbul ignore next */ "";
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {Element} target the root element
|
|
40
|
+
* @param {Element | Element[]} content the element(s) to hydrate
|
|
41
|
+
*/
|
|
42
|
+
export const hydrate = (target, content) => {
|
|
43
|
+
const wrapper = unwrap(content);
|
|
44
|
+
target.replaceChildren(
|
|
45
|
+
...(Array.from(wrapper.children)),
|
|
46
|
+
);
|
|
47
|
+
return target;
|
|
48
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "client",
|
|
3
|
+
"main": "./index.mjs",
|
|
4
|
+
"module": "./index.mjs",
|
|
5
|
+
"types": "./types.d.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./types.d.ts",
|
|
10
|
+
"import": "./index.mjs"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"vite-plugin-vanjs": "*",
|
|
15
|
+
"csstype": "*"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": false
|
|
18
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/// <reference path="global.d.ts" />
|
|
2
|
+
import * as CSS from "csstype";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Sets the attribute value of the given name of the given element.
|
|
6
|
+
*
|
|
7
|
+
* @param element the target element
|
|
8
|
+
* @param key the attribute name
|
|
9
|
+
* @param value the attribute value
|
|
10
|
+
*/
|
|
11
|
+
export const setAttribute: (
|
|
12
|
+
element: Element,
|
|
13
|
+
name: string,
|
|
14
|
+
value: boolean | string | number | null | undefined,
|
|
15
|
+
) => void;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Normalize the style value and convert it to a string
|
|
19
|
+
*
|
|
20
|
+
* @param source the style value
|
|
21
|
+
* @returns the normalized style string
|
|
22
|
+
*/
|
|
23
|
+
export const styleToString: (source: string | CSS.Properties) => string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Hydrate a target element with the given content(s).
|
|
27
|
+
*
|
|
28
|
+
* @param target the root element
|
|
29
|
+
* @param content the element(s) to hydrate
|
|
30
|
+
*/
|
|
31
|
+
export const hydrate: (
|
|
32
|
+
target: HTMLElement,
|
|
33
|
+
content: HTMLElement | HTMLElement[],
|
|
34
|
+
) => HTMLElement;
|
package/jsx/global.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
declare module "@vanjs/jsx" {
|
|
2
2
|
import type { ChildDom, Primitive } from "vanjs-core";
|
|
3
|
+
import type { Element as VanElement } from "mini-van-plate/van-plate";
|
|
3
4
|
export const Fragment = ({ children }: { children?: JSX.Element }) =>
|
|
4
5
|
JSX.Element;
|
|
5
|
-
export type VanElement = Element;
|
|
6
|
+
// export type VanElement = Element;
|
|
6
7
|
export type VanNode =
|
|
7
8
|
| Primitive
|
|
8
9
|
| ChildDom
|
|
@@ -12,12 +13,12 @@ declare module "@vanjs/jsx" {
|
|
|
12
13
|
| null;
|
|
13
14
|
|
|
14
15
|
export function jsx(
|
|
15
|
-
tag: string | ((props:
|
|
16
|
+
tag: string | ((props: unknown) => VanNode),
|
|
16
17
|
props: {
|
|
17
18
|
children?: VanNode;
|
|
18
19
|
style?: string | CSSProperties | (() => CSSProperties);
|
|
19
20
|
ref?: State<Element>;
|
|
20
|
-
[key: string]:
|
|
21
|
+
[key: string]: unknown;
|
|
21
22
|
},
|
|
22
23
|
): VanNode;
|
|
23
24
|
|
package/jsx/jsx.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
// deno-lint-ignore-file no-empty-interface ban-types
|
|
2
|
+
|
|
1
3
|
import * as csstype from "csstype";
|
|
2
|
-
import type { ChildDom,
|
|
4
|
+
import type { ChildDom, State } from "vanjs-core";
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Based on JSX types for Surplus and Inferno and adapted for `dom-expressions`.
|
|
@@ -16,7 +18,7 @@ export = JSX;
|
|
|
16
18
|
|
|
17
19
|
declare namespace JSX {
|
|
18
20
|
// type FunctionMaybe<T = unknown> = { (): T } | T;
|
|
19
|
-
type FunctionMaybe<T = unknown> = State<T> | T;
|
|
21
|
+
type FunctionMaybe<T = unknown> = (() => T) | State<T> | T;
|
|
20
22
|
type Element =
|
|
21
23
|
| ChildDom
|
|
22
24
|
| Node
|
|
@@ -52,13 +54,13 @@ declare namespace JSX {
|
|
|
52
54
|
|
|
53
55
|
interface BoundEventHandler<T, E extends Event> {
|
|
54
56
|
0: (
|
|
55
|
-
data:
|
|
57
|
+
data: unknown,
|
|
56
58
|
e: E & {
|
|
57
59
|
currentTarget: T;
|
|
58
60
|
target: DOMElement;
|
|
59
61
|
},
|
|
60
62
|
) => void;
|
|
61
|
-
1:
|
|
63
|
+
1: unknown;
|
|
62
64
|
}
|
|
63
65
|
type EventHandlerUnion<T, E extends Event> =
|
|
64
66
|
| EventHandler<T, E>
|
|
@@ -85,10 +87,12 @@ declare namespace JSX {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
interface IntrinsicAttributes {
|
|
88
|
-
ref?: unknown | ((e: unknown) => void);
|
|
90
|
+
// ref?: unknown | ((e: unknown) => void);
|
|
91
|
+
ref?: State<T>;
|
|
89
92
|
}
|
|
90
93
|
interface CustomAttributes<T> {
|
|
91
|
-
ref?: State<T> | T | ((el: T) => void);
|
|
94
|
+
// ref?: State<T> | T | ((el: T) => void);
|
|
95
|
+
ref?: State<T>;
|
|
92
96
|
}
|
|
93
97
|
interface ExplicitProperties {}
|
|
94
98
|
interface ExplicitAttributes {}
|
|
@@ -295,7 +299,11 @@ declare namespace JSX {
|
|
|
295
299
|
|
|
296
300
|
interface CSSProperties extends csstype.PropertiesHyphen {
|
|
297
301
|
// Override
|
|
298
|
-
[key: `-${string}`]:
|
|
302
|
+
[key: `-${string}`]:
|
|
303
|
+
| State<string | number | undefined>
|
|
304
|
+
| string
|
|
305
|
+
| number
|
|
306
|
+
| undefined;
|
|
299
307
|
}
|
|
300
308
|
|
|
301
309
|
type HTMLAutocapitalize =
|
|
@@ -719,7 +727,7 @@ declare namespace JSX {
|
|
|
719
727
|
translate?: FunctionMaybe<"yes" | "no">;
|
|
720
728
|
about?: FunctionMaybe<string>;
|
|
721
729
|
datatype?: FunctionMaybe<string>;
|
|
722
|
-
inlist?: FunctionMaybe<
|
|
730
|
+
inlist?: FunctionMaybe<unknown>;
|
|
723
731
|
popover?: FunctionMaybe<boolean | "manual" | "auto">;
|
|
724
732
|
prefix?: FunctionMaybe<string>;
|
|
725
733
|
property?: FunctionMaybe<string>;
|
|
@@ -768,7 +776,7 @@ declare namespace JSX {
|
|
|
768
776
|
>;
|
|
769
777
|
}
|
|
770
778
|
interface AnchorHTMLAttributes<T> extends HTMLAttributes<T> {
|
|
771
|
-
download?: FunctionMaybe<
|
|
779
|
+
download?: FunctionMaybe<unknown>;
|
|
772
780
|
href?: FunctionMaybe<string>;
|
|
773
781
|
hreflang?: FunctionMaybe<string>;
|
|
774
782
|
media?: FunctionMaybe<string>;
|
|
@@ -783,7 +791,7 @@ declare namespace JSX {
|
|
|
783
791
|
interface AreaHTMLAttributes<T> extends HTMLAttributes<T> {
|
|
784
792
|
alt?: FunctionMaybe<string>;
|
|
785
793
|
coords?: FunctionMaybe<string>;
|
|
786
|
-
download?: FunctionMaybe<
|
|
794
|
+
download?: FunctionMaybe<unknown>;
|
|
787
795
|
href?: FunctionMaybe<string>;
|
|
788
796
|
hreflang?: FunctionMaybe<string>;
|
|
789
797
|
ping?: FunctionMaybe<string>;
|
package/jsx/jsx.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import van from "@vanjs/van";
|
|
2
2
|
import setup from "@vanjs/setup";
|
|
3
|
-
import { setAttribute, styleToString } from "
|
|
3
|
+
import { setAttribute, styleToString } from "@vanjs/client";
|
|
4
4
|
|
|
5
5
|
export const jsx = (jsxTag, { children, ref, style, ...props }) => {
|
|
6
6
|
if (typeof jsxTag === "string") {
|
|
@@ -28,6 +28,7 @@ export const jsx = (jsxTag, { children, ref, style, ...props }) => {
|
|
|
28
28
|
|
|
29
29
|
setAttribute(newElement, k, value);
|
|
30
30
|
}
|
|
31
|
+
/* istanbul ignore else */
|
|
31
32
|
if (style) {
|
|
32
33
|
if (typeof style === "function") {
|
|
33
34
|
van.derive(() => newElement.style.cssText = styleToString(style()));
|
|
@@ -42,5 +43,5 @@ export const jsx = (jsxTag, { children, ref, style, ...props }) => {
|
|
|
42
43
|
|
|
43
44
|
return typeof jsxTag === "function"
|
|
44
45
|
? jsxTag({ children, ref, style, ...props })
|
|
45
|
-
: null;
|
|
46
|
+
: /* istanbul ignore next */ null;
|
|
46
47
|
};
|
package/jsx/package.json
CHANGED
package/jsx/types.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference path="global.d.ts" />
|
|
2
|
+
import type { Fragment } from "./fragment";
|
|
3
|
+
|
|
4
|
+
declare function jsx(
|
|
5
|
+
type: unknown,
|
|
6
|
+
props: unknown,
|
|
7
|
+
): () =>
|
|
8
|
+
| (Node & {
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
})
|
|
11
|
+
| (Node & {
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
})[];
|
|
14
|
+
|
|
15
|
+
export type { JSX } from "./jsx";
|
|
16
|
+
export { Fragment, jsx, jsx as jsxDEV, jsx as jsxs };
|
package/meta/Head.mjs
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import setup from "@vanjs/setup";
|
|
2
|
+
import { getTagKey } from "./helpers.mjs";
|
|
3
|
+
|
|
4
|
+
/** @typedef {typeof import("./types.d.ts").getHeadTags} GetTags */
|
|
5
|
+
/** @typedef {typeof import("./types.d.ts").createHeadTags} CreateTags */
|
|
6
|
+
/** @typedef {typeof import("./types.d.ts").resetHeadTags} ResetTags */
|
|
7
|
+
/** @typedef {typeof import("./types.d.ts").initializeHeadTags} InitializeTags */
|
|
8
|
+
/** @typedef {import("./types.d.ts").AddMeta} AddMeta */
|
|
9
|
+
/** @typedef {typeof import("./types.d.ts").Head} HeadComp */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create a new Map for each request on server
|
|
13
|
+
* @type {CreateTags}
|
|
14
|
+
*/
|
|
15
|
+
const createHeadTags = () => new Map();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get the current head tags. Use a factory pattern to get the right store
|
|
19
|
+
* on the server and the client.
|
|
20
|
+
* @type {GetTags}
|
|
21
|
+
*/
|
|
22
|
+
const getHeadTags = (() => {
|
|
23
|
+
if (setup.isServer) {
|
|
24
|
+
// On server, create one Map per request scope
|
|
25
|
+
let serverHeadTags;
|
|
26
|
+
return () => {
|
|
27
|
+
if (!serverHeadTags) {
|
|
28
|
+
serverHeadTags = createHeadTags();
|
|
29
|
+
}
|
|
30
|
+
return serverHeadTags;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// On client, use a singleton
|
|
34
|
+
const clientHeadTags = createHeadTags();
|
|
35
|
+
return () => clientHeadTags;
|
|
36
|
+
})();
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Clear all head tags
|
|
40
|
+
* @type {ResetTags}
|
|
41
|
+
*/
|
|
42
|
+
export const resetHeadTags = () => {
|
|
43
|
+
const tags = getHeadTags();
|
|
44
|
+
tags.clear();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Initialize the head tags
|
|
49
|
+
* @type {InitializeTags}
|
|
50
|
+
*/
|
|
51
|
+
export const initializeHeadTags = () => {
|
|
52
|
+
const tags = getHeadTags();
|
|
53
|
+
/* istanbul ignore else */
|
|
54
|
+
if (!tags.size && !setup.isServer) {
|
|
55
|
+
[...document.head.children].forEach((tag) => {
|
|
56
|
+
tags.set(getTagKey(tag), tag);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Add a new meta tag
|
|
63
|
+
* @type {AddMeta}
|
|
64
|
+
*/
|
|
65
|
+
export const addMeta = (tag) => {
|
|
66
|
+
if (!tag) return;
|
|
67
|
+
const tags = getHeadTags();
|
|
68
|
+
const key = getTagKey(tag);
|
|
69
|
+
tags.set(key, tag);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get the head tags
|
|
74
|
+
* @type {HeadComp}
|
|
75
|
+
*/
|
|
76
|
+
export const Head = () => {
|
|
77
|
+
return () => {
|
|
78
|
+
const tags = getHeadTags();
|
|
79
|
+
return Array.from(tags.values());
|
|
80
|
+
};
|
|
81
|
+
};
|
package/meta/global.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
declare module "@vanjs/meta" {
|
|
2
|
+
import { type PropsWithKnownKeys } from "vanjs-core";
|
|
3
|
+
import type {
|
|
4
|
+
Element as VanElement,
|
|
5
|
+
TagFunc,
|
|
6
|
+
} from "mini-van-plate/van-plate";
|
|
7
|
+
|
|
8
|
+
export const createHeadTags: () => Map<
|
|
9
|
+
string,
|
|
10
|
+
SupportedTags | TagFunc
|
|
11
|
+
>;
|
|
12
|
+
export const getHeadTags: () => Map<
|
|
13
|
+
string,
|
|
14
|
+
SupportedTags | TagFunc
|
|
15
|
+
>;
|
|
16
|
+
export type ResetTags = () => void;
|
|
17
|
+
export type InitializeTags = () => void;
|
|
18
|
+
|
|
19
|
+
export type SupportedTags =
|
|
20
|
+
| HTMLTitleElement
|
|
21
|
+
| HTMLMetaElement
|
|
22
|
+
| HTMLScriptElement
|
|
23
|
+
| HTMLLinkElement
|
|
24
|
+
| HTMLStyleElement;
|
|
25
|
+
|
|
26
|
+
export type TagProps = PropsWithKnownKeys<SupportedTags>;
|
|
27
|
+
|
|
28
|
+
export type HeadTags = SupportedTags[] | TagFunc[];
|
|
29
|
+
|
|
30
|
+
export type AddMeta = (tag?: TagProps) => void;
|
|
31
|
+
|
|
32
|
+
// export declare const Head: () => () => TagFunc[];
|
|
33
|
+
export declare const Head: () => () => SupportedTags[];
|
|
34
|
+
export const Title: (
|
|
35
|
+
props: PropsWithKnownKeys<HTMLTitleElement>,
|
|
36
|
+
content?: string,
|
|
37
|
+
) => null;
|
|
38
|
+
export const Meta: (props: PropsWithKnownKeys<HTMLMetaElement>) => null;
|
|
39
|
+
export const Style: (
|
|
40
|
+
props: PropsWithKnownKeys<HTMLStyleElement>,
|
|
41
|
+
content?: string,
|
|
42
|
+
) => null;
|
|
43
|
+
export const Link: (props: PropsWithKnownKeys<HTMLLinkElement>) => null;
|
|
44
|
+
export const Script: (
|
|
45
|
+
props: PropsWithKnownKeys<HTMLScriptElement>,
|
|
46
|
+
content?: string,
|
|
47
|
+
) => null;
|
|
48
|
+
|
|
49
|
+
export type ParseAttributes = (
|
|
50
|
+
attributeString: string,
|
|
51
|
+
) => Record<string, string>;
|
|
52
|
+
|
|
53
|
+
export type GetTagAttribute = (tag: TagProps) => string;
|
|
54
|
+
|
|
55
|
+
export type GetTagKey = (tag: TagProps) => string;
|
|
56
|
+
|
|
57
|
+
export const initializeHeadTags: InitializeTags;
|
|
58
|
+
export const resetHeadTags: ResetTags;
|
|
59
|
+
export const addMeta: AddMeta;
|
|
60
|
+
}
|