@pyreon/zero 0.14.0 → 0.16.0
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/lib/api-routes-Ci0kVmM4.js +146 -0
- package/lib/client.js +7 -2
- package/lib/csp.js +19 -9
- package/lib/env.js +6 -6
- package/lib/font.js +3 -3
- package/lib/{fs-router-CQ7Zxeca.js → fs-router-MewHc5SB.js} +56 -24
- package/lib/i18n-routing.js +112 -1
- package/lib/image-plugin.js +4 -0
- package/lib/image.js +141 -108
- package/lib/index.js +253 -132
- package/lib/link.js +1 -49
- package/lib/og-image.js +5 -5
- package/lib/rolldown-runtime-CjeV3_4I.js +18 -0
- package/lib/script.js +115 -74
- package/lib/seo.js +186 -15
- package/lib/server.js +275 -1247
- package/lib/theme.js +1 -50
- package/lib/types/config.d.ts +275 -3
- package/lib/types/env.d.ts +2 -2
- package/lib/types/i18n-routing.d.ts +197 -6
- package/lib/types/image.d.ts +105 -5
- package/lib/types/index.d.ts +640 -178
- package/lib/types/link.d.ts +3 -3
- package/lib/types/script.d.ts +78 -6
- package/lib/types/seo.d.ts +128 -4
- package/lib/types/server.d.ts +603 -77
- package/lib/types/theme.d.ts +2 -2
- package/lib/vite-plugin-xjWZwudX.js +2454 -0
- package/package.json +16 -13
- package/src/adapters/bun.ts +20 -1
- package/src/adapters/cloudflare.ts +78 -1
- package/src/adapters/index.ts +25 -3
- package/src/adapters/netlify.ts +63 -1
- package/src/adapters/node.ts +25 -1
- package/src/adapters/static.ts +26 -1
- package/src/adapters/validate.ts +8 -1
- package/src/adapters/vercel.ts +76 -1
- package/src/adapters/warn-missing-env.ts +49 -0
- package/src/app.ts +35 -1
- package/src/client.ts +18 -0
- package/src/csp.ts +28 -12
- package/src/entry-server.ts +55 -5
- package/src/env.ts +7 -7
- package/src/font.ts +3 -3
- package/src/fs-router.ts +123 -4
- package/src/i18n-routing.ts +246 -12
- package/src/image.tsx +242 -91
- package/src/index.ts +4 -4
- package/src/isr.ts +24 -6
- package/src/manifest.ts +675 -0
- package/src/og-image.ts +5 -5
- package/src/script.tsx +159 -36
- package/src/seo.ts +346 -15
- package/src/server.ts +10 -2
- package/src/ssg-plugin.ts +1523 -0
- package/src/types.ts +329 -19
- package/src/vercel-revalidate-handler.ts +204 -0
- package/src/vite-plugin.ts +326 -68
- package/lib/actions.js.map +0 -1
- package/lib/ai.js.map +0 -1
- package/lib/api-routes.js.map +0 -1
- package/lib/cache.js.map +0 -1
- package/lib/client.js.map +0 -1
- package/lib/compression.js.map +0 -1
- package/lib/config.js.map +0 -1
- package/lib/cors.js.map +0 -1
- package/lib/csp.js.map +0 -1
- package/lib/env.js.map +0 -1
- package/lib/favicon.js.map +0 -1
- package/lib/font.js.map +0 -1
- package/lib/fs-router-3xzp-4Wj.js.map +0 -1
- package/lib/fs-router-CQ7Zxeca.js.map +0 -1
- package/lib/i18n-routing.js.map +0 -1
- package/lib/image-plugin.js.map +0 -1
- package/lib/image.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/link.js.map +0 -1
- package/lib/logger.js.map +0 -1
- package/lib/meta.js.map +0 -1
- package/lib/middleware.js.map +0 -1
- package/lib/og-image.js.map +0 -1
- package/lib/rate-limit.js.map +0 -1
- package/lib/script.js.map +0 -1
- package/lib/seo.js.map +0 -1
- package/lib/server.js.map +0 -1
- package/lib/testing.js.map +0 -1
- package/lib/theme.js.map +0 -1
- package/lib/types/actions.d.ts.map +0 -1
- package/lib/types/ai.d.ts.map +0 -1
- package/lib/types/api-routes.d.ts.map +0 -1
- package/lib/types/cache.d.ts.map +0 -1
- package/lib/types/client.d.ts.map +0 -1
- package/lib/types/compression.d.ts.map +0 -1
- package/lib/types/config.d.ts.map +0 -1
- package/lib/types/cors.d.ts.map +0 -1
- package/lib/types/csp.d.ts.map +0 -1
- package/lib/types/env.d.ts.map +0 -1
- package/lib/types/favicon.d.ts.map +0 -1
- package/lib/types/font.d.ts.map +0 -1
- package/lib/types/i18n-routing.d.ts.map +0 -1
- package/lib/types/image-plugin.d.ts.map +0 -1
- package/lib/types/image.d.ts.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/link.d.ts.map +0 -1
- package/lib/types/logger.d.ts.map +0 -1
- package/lib/types/meta.d.ts.map +0 -1
- package/lib/types/middleware.d.ts.map +0 -1
- package/lib/types/og-image.d.ts.map +0 -1
- package/lib/types/rate-limit.d.ts.map +0 -1
- package/lib/types/script.d.ts.map +0 -1
- package/lib/types/seo.d.ts.map +0 -1
- package/lib/types/server.d.ts.map +0 -1
- package/lib/types/testing.d.ts.map +0 -1
- package/lib/types/theme.d.ts.map +0 -1
package/lib/image.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRef, onMount, onUnmount } from "@pyreon/core";
|
|
2
2
|
import { signal } from "@pyreon/reactivity";
|
|
3
|
+
import { jsx, jsxs } from "@pyreon/core/jsx-runtime";
|
|
3
4
|
|
|
4
5
|
//#region src/utils/use-intersection-observer.ts
|
|
5
6
|
/**
|
|
@@ -25,83 +26,37 @@ function useIntersectionObserver(getElement, onIntersect, rootMargin = "200px")
|
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region ../../core/core/lib/jsx-runtime.js
|
|
30
|
-
/**
|
|
31
|
-
* Hyperscript function — the compiled output of JSX.
|
|
32
|
-
* `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
|
|
33
|
-
*
|
|
34
|
-
* Generic on P so TypeScript validates props match the component's signature
|
|
35
|
-
* at the call site, then stores the result in the loosely-typed VNode.
|
|
36
|
-
*/
|
|
37
|
-
/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */
|
|
38
|
-
const EMPTY_PROPS = {};
|
|
39
|
-
function h(type, props, ...children) {
|
|
40
|
-
return {
|
|
41
|
-
type,
|
|
42
|
-
props: props ?? EMPTY_PROPS,
|
|
43
|
-
children: normalizeChildren(children),
|
|
44
|
-
key: props?.key ?? null
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function normalizeChildren(children) {
|
|
48
|
-
for (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);
|
|
49
|
-
return children;
|
|
50
|
-
}
|
|
51
|
-
function flattenChildren(children) {
|
|
52
|
-
const result = [];
|
|
53
|
-
for (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));
|
|
54
|
-
else result.push(child);
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* JSX automatic runtime.
|
|
59
|
-
*
|
|
60
|
-
* When tsconfig has `"jsxImportSource": "@pyreon/core"`, the TS/bundler compiler
|
|
61
|
-
* rewrites JSX to imports from this file automatically:
|
|
62
|
-
* <div class="x" /> → jsx("div", { class: "x" })
|
|
63
|
-
*/
|
|
64
|
-
function jsx(type, props, key) {
|
|
65
|
-
const { children, ...rest } = props;
|
|
66
|
-
const propsWithKey = key != null ? {
|
|
67
|
-
...rest,
|
|
68
|
-
key
|
|
69
|
-
} : rest;
|
|
70
|
-
if (typeof type === "function") return h(type, children !== void 0 ? {
|
|
71
|
-
...propsWithKey,
|
|
72
|
-
children
|
|
73
|
-
} : propsWithKey);
|
|
74
|
-
return h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
|
|
75
|
-
}
|
|
76
|
-
const jsxs = jsx;
|
|
77
|
-
|
|
78
29
|
//#endregion
|
|
79
30
|
//#region src/image.tsx
|
|
80
31
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
32
|
+
* Composable that provides all image optimization behavior — lazy loading,
|
|
33
|
+
* srcset/sizes resolution, format selection, blur-placeholder state,
|
|
34
|
+
* load tracking.
|
|
83
35
|
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* <Image {...hero} alt="Hero" priority />
|
|
36
|
+
* Use this for full control when `createImage` is too opinionated about
|
|
37
|
+
* the surrounding markup (e.g. custom container layouts, non-`<div>`
|
|
38
|
+
* wrappers, additional overlay elements).
|
|
88
39
|
*
|
|
89
40
|
* @example
|
|
90
|
-
*
|
|
91
|
-
*
|
|
41
|
+
* function MyImage(props: ImageProps) {
|
|
42
|
+
* const img = useImage(props)
|
|
43
|
+
* return (
|
|
44
|
+
* <figure ref={img.containerRef} style={img.containerStyle}>
|
|
45
|
+
* <img
|
|
46
|
+
* src={img.src}
|
|
47
|
+
* srcSet={img.srcSet}
|
|
48
|
+
* sizes={img.sizes}
|
|
49
|
+
* alt={props.alt}
|
|
50
|
+
* loading={img.loading}
|
|
51
|
+
* onLoad={img.handleLoad}
|
|
52
|
+
* style={img.imageStyle}
|
|
53
|
+
* />
|
|
54
|
+
* <figcaption>{props.alt}</figcaption>
|
|
55
|
+
* </figure>
|
|
56
|
+
* )
|
|
57
|
+
* }
|
|
92
58
|
*/
|
|
93
|
-
function
|
|
94
|
-
if (props.raw) return /* @__PURE__ */ jsx("img", {
|
|
95
|
-
src: props.src,
|
|
96
|
-
alt: props.alt,
|
|
97
|
-
width: props.width,
|
|
98
|
-
height: props.height,
|
|
99
|
-
class: props.class,
|
|
100
|
-
style: props.style,
|
|
101
|
-
decoding: props.decoding ?? "async",
|
|
102
|
-
loading: props.loading ?? "lazy",
|
|
103
|
-
fetchPriority: props.priority ? "high" : void 0
|
|
104
|
-
});
|
|
59
|
+
function useImage(props) {
|
|
105
60
|
const isEager = props.priority || props.loading === "eager";
|
|
106
61
|
const loaded = signal(isEager);
|
|
107
62
|
const inView = signal(isEager);
|
|
@@ -109,7 +64,7 @@ function Image(props) {
|
|
|
109
64
|
const resolvedSrcset = typeof props.srcset === "string" ? props.srcset : props.srcset?.map((s) => `${s.src} ${s.width}w`).join(", ");
|
|
110
65
|
const sizes = props.sizes ?? "100vw";
|
|
111
66
|
const fit = props.fit ?? "cover";
|
|
112
|
-
const hasFormats = props.formats && props.formats.length > 0;
|
|
67
|
+
const hasFormats = !!(props.formats && props.formats.length > 0);
|
|
113
68
|
const aspectRatio = `${props.width} / ${props.height}`;
|
|
114
69
|
if (!isEager) useIntersectionObserver(() => containerRef.current ?? void 0, () => inView.set(true));
|
|
115
70
|
const containerStyle = [
|
|
@@ -120,54 +75,132 @@ function Image(props) {
|
|
|
120
75
|
"width: 100%",
|
|
121
76
|
props.style
|
|
122
77
|
].filter(Boolean).join("; ");
|
|
123
|
-
const
|
|
78
|
+
const imageStyle = () => [
|
|
79
|
+
"display: block",
|
|
80
|
+
"width: 100%",
|
|
81
|
+
"height: 100%",
|
|
82
|
+
`object-fit: ${fit}`,
|
|
83
|
+
"transition: opacity 0.3s ease",
|
|
84
|
+
props.placeholder && !loaded() ? "opacity: 0" : "opacity: 1"
|
|
85
|
+
].join("; ");
|
|
86
|
+
const placeholderStyle = () => [
|
|
87
|
+
"position: absolute",
|
|
88
|
+
"inset: 0",
|
|
89
|
+
"width: 100%",
|
|
90
|
+
"height: 100%",
|
|
91
|
+
"object-fit: cover",
|
|
92
|
+
"filter: blur(20px)",
|
|
93
|
+
"transform: scale(1.1)",
|
|
94
|
+
"transition: opacity 0.4s ease",
|
|
95
|
+
loaded() ? "opacity: 0; pointer-events: none" : "opacity: 1"
|
|
96
|
+
].join("; ");
|
|
97
|
+
return {
|
|
98
|
+
containerRef,
|
|
99
|
+
inView,
|
|
100
|
+
loaded,
|
|
124
101
|
src: () => inView() ? props.src : "",
|
|
125
102
|
srcSet: () => !hasFormats && inView() && resolvedSrcset ? resolvedSrcset : "",
|
|
126
103
|
sizes: resolvedSrcset ? sizes : void 0,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
104
|
+
aspectRatio,
|
|
105
|
+
containerStyle,
|
|
106
|
+
imageStyle,
|
|
107
|
+
placeholderStyle,
|
|
130
108
|
loading: isEager ? "eager" : "lazy",
|
|
131
|
-
decoding: props.decoding ?? "async",
|
|
132
109
|
fetchPriority: props.priority ? "high" : void 0,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
110
|
+
handleLoad: () => loaded.set(true),
|
|
111
|
+
formats: props.formats,
|
|
112
|
+
hasFormats
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Higher-order component that wraps any component with image optimization.
|
|
117
|
+
*
|
|
118
|
+
* The wrapped component receives {@link ImageRenderProps} with the pre-rendered
|
|
119
|
+
* `image` JSX (bare `<img>` OR `<picture>` tree depending on formats), the
|
|
120
|
+
* pre-rendered `placeholder` JSX, and the container ref + styles. Consumers
|
|
121
|
+
* compose those pieces with whatever wrapper element / layout they want.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* // Custom figure-based image with caption
|
|
125
|
+
* const FigureImage = createImage((props) => (
|
|
126
|
+
* <figure ref={props.containerRef} class={props.class} style={props.containerStyle}>
|
|
127
|
+
* {props.placeholder}
|
|
128
|
+
* {props.image}
|
|
129
|
+
* <figcaption>Caption goes here</figcaption>
|
|
130
|
+
* </figure>
|
|
131
|
+
* ))
|
|
132
|
+
*
|
|
133
|
+
* // Usage — identical to default <Image>
|
|
134
|
+
* <FigureImage src="/hero.jpg" alt="Hero" width={1200} height={630} />
|
|
135
|
+
*/
|
|
136
|
+
function createImage(Component) {
|
|
137
|
+
return function WrappedImage(props) {
|
|
138
|
+
if (props.raw) return /* @__PURE__ */ jsx("img", {
|
|
139
|
+
src: props.src,
|
|
140
|
+
alt: props.alt,
|
|
141
|
+
width: props.width,
|
|
142
|
+
height: props.height,
|
|
143
|
+
class: props.class,
|
|
144
|
+
style: props.style,
|
|
145
|
+
decoding: props.decoding ?? "async",
|
|
146
|
+
loading: props.loading ?? "lazy",
|
|
147
|
+
fetchPriority: props.priority ? "high" : void 0
|
|
148
|
+
});
|
|
149
|
+
const img = useImage(props);
|
|
150
|
+
const imgEl = /* @__PURE__ */ jsx("img", {
|
|
151
|
+
src: img.src,
|
|
152
|
+
srcSet: img.srcSet,
|
|
153
|
+
sizes: img.sizes,
|
|
154
|
+
alt: props.alt,
|
|
155
|
+
width: props.width,
|
|
156
|
+
height: props.height,
|
|
157
|
+
loading: img.loading,
|
|
158
|
+
decoding: props.decoding ?? "async",
|
|
159
|
+
fetchPriority: img.fetchPriority,
|
|
160
|
+
onLoad: img.handleLoad,
|
|
161
|
+
style: img.imageStyle
|
|
162
|
+
});
|
|
163
|
+
const placeholderEl = props.placeholder ? /* @__PURE__ */ jsx("img", {
|
|
148
164
|
src: props.placeholder,
|
|
149
165
|
alt: "",
|
|
150
166
|
"aria-hidden": "true",
|
|
151
167
|
loading: "eager",
|
|
152
|
-
style:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
"width: 100%",
|
|
156
|
-
"height: 100%",
|
|
157
|
-
"object-fit: cover",
|
|
158
|
-
"filter: blur(20px)",
|
|
159
|
-
"transform: scale(1.1)",
|
|
160
|
-
"transition: opacity 0.4s ease",
|
|
161
|
-
loaded() ? "opacity: 0; pointer-events: none" : "opacity: 1"
|
|
162
|
-
].join("; ")
|
|
163
|
-
}), hasFormats ? /* @__PURE__ */ jsxs("picture", { children: [props.formats?.map((fmt) => /* @__PURE__ */ jsx("source", {
|
|
168
|
+
style: img.placeholderStyle
|
|
169
|
+
}) : null;
|
|
170
|
+
const imageEl = img.hasFormats ? /* @__PURE__ */ jsxs("picture", { children: [img.formats?.map((fmt) => /* @__PURE__ */ jsx("source", {
|
|
164
171
|
type: fmt.type,
|
|
165
|
-
srcSet: () => inView() ? fmt.srcset ?? "" : "",
|
|
166
|
-
sizes
|
|
167
|
-
})), imgEl] }) : imgEl
|
|
168
|
-
|
|
172
|
+
srcSet: () => img.inView() ? fmt.srcset ?? "" : "",
|
|
173
|
+
sizes: img.sizes
|
|
174
|
+
})), imgEl] }) : imgEl;
|
|
175
|
+
return /* @__PURE__ */ jsx(Component, {
|
|
176
|
+
containerRef: img.containerRef,
|
|
177
|
+
class: props.class,
|
|
178
|
+
containerStyle: img.containerStyle,
|
|
179
|
+
placeholder: placeholderEl,
|
|
180
|
+
image: imageEl
|
|
181
|
+
});
|
|
182
|
+
};
|
|
169
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Default optimized image component with lazy loading, responsive srcset,
|
|
186
|
+
* `<picture>` multi-format support, and blur-up placeholders.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* // With imagePlugin — spread the import directly
|
|
190
|
+
* import hero from "./hero.jpg?optimize"
|
|
191
|
+
* <Image {...hero} alt="Hero" priority />
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* // Manual usage
|
|
195
|
+
* <Image src="/hero.jpg" alt="Hero" width={1200} height={630} />
|
|
196
|
+
*/
|
|
197
|
+
const Image = createImage((props) => /* @__PURE__ */ jsxs("div", {
|
|
198
|
+
ref: props.containerRef,
|
|
199
|
+
class: props.class,
|
|
200
|
+
style: props.containerStyle,
|
|
201
|
+
children: [props.placeholder, props.image]
|
|
202
|
+
}));
|
|
170
203
|
|
|
171
204
|
//#endregion
|
|
172
|
-
export { Image };
|
|
205
|
+
export { Image, createImage, useImage };
|
|
173
206
|
//# sourceMappingURL=image.js.map
|