zuby 1.0.64 → 1.0.65
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/config.js +12 -0
- package/contexts/globalContext.d.ts +32 -1
- package/image/getNearestSize.d.ts +18 -0
- package/image/getNearestSize.js +32 -0
- package/image/imageLoader.d.ts +8 -0
- package/image/imageLoader.js +13 -0
- package/package.json +1 -1
- package/plugins/contextPlugin/index.d.ts +2 -0
- package/plugins/contextPlugin/index.js +22 -1
- package/plugins/prerenderPlugin/index.js +11 -1
- package/server/index.js +7 -2
- package/server/zubyServer.d.ts +2 -1
- package/server/zubyServer.js +11 -2
- package/types.d.ts +102 -0
- package/types.js +13 -0
package/config.js
CHANGED
|
@@ -5,6 +5,8 @@ import { randomBytes } from 'crypto';
|
|
|
5
5
|
import { bundleRequire } from 'bundle-require';
|
|
6
6
|
import { createLogger } from './logger/index.js';
|
|
7
7
|
import { TEMPLATES } from './templates/types.js';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
8
10
|
// Plugins
|
|
9
11
|
import contextPlugin from './plugins/contextPlugin/index.js';
|
|
10
12
|
import chunkNamingPlugin from './plugins/chunkNamingPlugin/index.js';
|
|
@@ -13,6 +15,9 @@ import prerenderPlugin from './plugins/prerenderPlugin/index.js';
|
|
|
13
15
|
import standaloneBuildPlugin from './plugins/dependenciesPlugin/index.js';
|
|
14
16
|
import preloadPlugin from './plugins/preloadPlugin/index.js';
|
|
15
17
|
import injectPlugin from './plugins/injectPlugin/index.js';
|
|
18
|
+
import { normalizePath } from './utils/pathUtils.js';
|
|
19
|
+
import { dirname, resolve } from 'path';
|
|
20
|
+
import { fileURLToPath } from 'url';
|
|
16
21
|
let zubyInternalConfig;
|
|
17
22
|
/**
|
|
18
23
|
* Returns the path to the ZubyConfig file.
|
|
@@ -163,6 +168,13 @@ export const mergeDefaultConfig = async (config) => {
|
|
|
163
168
|
config.minifyJS = config.minifyJS ?? true;
|
|
164
169
|
config.compress = config.compress ?? true;
|
|
165
170
|
config.poweredByHeader = config.poweredByHeader ?? true;
|
|
171
|
+
// Image config
|
|
172
|
+
config.image = config.image ?? {};
|
|
173
|
+
config.image.sizes = config.image.sizes ?? [160, 320, 640, 768, 1024, 1280, 1536, 1920, 2048];
|
|
174
|
+
config.image.loader =
|
|
175
|
+
config.image.loader ?? normalizePath(resolve(__dirname, 'image', 'imageLoader.js'));
|
|
176
|
+
config.image.defaultFormat = config.image.defaultFormat ?? 'webp';
|
|
177
|
+
config.image.defaultQuality = config.image.defaultQuality ?? 80;
|
|
166
178
|
// Build ID generator
|
|
167
179
|
config.generateBuildId = config.generateBuildId ?? generateDefaultBuildId;
|
|
168
180
|
// Global props
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LazyTemplate } from '../templates/types.js';
|
|
2
|
-
import { RenderToStream, RenderToString } from '../types.js';
|
|
2
|
+
import { ImageFormat, ImageLoader, RenderToStream, RenderToString } from '../types.js';
|
|
3
3
|
export interface GlobalContext {
|
|
4
4
|
/**
|
|
5
5
|
* The array with templates.
|
|
@@ -56,6 +56,37 @@ export interface GlobalContext {
|
|
|
56
56
|
* on both client and server side.
|
|
57
57
|
*/
|
|
58
58
|
props: Record<string, any>;
|
|
59
|
+
/**
|
|
60
|
+
* The image component options.
|
|
61
|
+
*/
|
|
62
|
+
image?: {
|
|
63
|
+
/**
|
|
64
|
+
* The path to the image loader function.
|
|
65
|
+
* @default 'zuby/imageLoader.js'
|
|
66
|
+
*/
|
|
67
|
+
loader?: ImageLoader;
|
|
68
|
+
/**
|
|
69
|
+
* The array of image sizes
|
|
70
|
+
* that will be used to generate image src.
|
|
71
|
+
* Zuby.js will try to use the closest size to the actual specified size.
|
|
72
|
+
*/
|
|
73
|
+
sizes?: number[];
|
|
74
|
+
/**
|
|
75
|
+
* The default format of the image,
|
|
76
|
+
* that will be passed to the image loader function
|
|
77
|
+
* if the format is not specified.
|
|
78
|
+
* @default 'webp'
|
|
79
|
+
*/
|
|
80
|
+
defaultFormat?: ImageFormat;
|
|
81
|
+
/**
|
|
82
|
+
* The default quality of the image,
|
|
83
|
+
* that will be passed to the image loader function
|
|
84
|
+
* if the quality is not specified.
|
|
85
|
+
* This should be a number between 0 and 100.
|
|
86
|
+
* @default 75
|
|
87
|
+
*/
|
|
88
|
+
defaultQuality?: number;
|
|
89
|
+
};
|
|
59
90
|
/**
|
|
60
91
|
* The global server props for the site
|
|
61
92
|
* that will be passed to all pages
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GlobalContext } from '../contexts/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adjust the image size
|
|
4
|
+
* to closest matching size from the image.sizes config.
|
|
5
|
+
* @param context - GlobalContext
|
|
6
|
+
* @param height - The height of the image
|
|
7
|
+
* @param width - The width of the image
|
|
8
|
+
*/
|
|
9
|
+
export default function getNearestSize(context: GlobalContext, width: number | undefined, height: number | undefined): {
|
|
10
|
+
width: number | undefined;
|
|
11
|
+
height: number | undefined;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Returns the nearest size from the array of sizes.
|
|
15
|
+
* @param size - The size to compare
|
|
16
|
+
* @param sizes - The array of sizes
|
|
17
|
+
*/
|
|
18
|
+
export declare function getNearestSizeFromArray(size: number, sizes: number[]): number;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adjust the image size
|
|
3
|
+
* to closest matching size from the image.sizes config.
|
|
4
|
+
* @param context - GlobalContext
|
|
5
|
+
* @param height - The height of the image
|
|
6
|
+
* @param width - The width of the image
|
|
7
|
+
*/
|
|
8
|
+
export default function getNearestSize(context, width, height) {
|
|
9
|
+
const sizes = context.image?.sizes || [];
|
|
10
|
+
if (width && height) {
|
|
11
|
+
const heightRatio = height / width;
|
|
12
|
+
width = getNearestSizeFromArray(width, sizes);
|
|
13
|
+
height = width * heightRatio;
|
|
14
|
+
}
|
|
15
|
+
else if (width) {
|
|
16
|
+
width = getNearestSizeFromArray(width, sizes);
|
|
17
|
+
}
|
|
18
|
+
else if (height) {
|
|
19
|
+
height = getNearestSizeFromArray(height, sizes);
|
|
20
|
+
}
|
|
21
|
+
return { width, height };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns the nearest size from the array of sizes.
|
|
25
|
+
* @param size - The size to compare
|
|
26
|
+
* @param sizes - The array of sizes
|
|
27
|
+
*/
|
|
28
|
+
export function getNearestSizeFromArray(size, sizes) {
|
|
29
|
+
return sizes.reduce((prev, curr) => {
|
|
30
|
+
return Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ImageLoaderOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The default image loader for Zuby.js
|
|
4
|
+
* that is used to generate image URLs
|
|
5
|
+
* for your project when <Image> component is used.
|
|
6
|
+
* @param options - ImageLoaderOptions
|
|
7
|
+
*/
|
|
8
|
+
export default function imageLoader({ context, src }: ImageLoaderOptions): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The default image loader for Zuby.js
|
|
3
|
+
* that is used to generate image URLs
|
|
4
|
+
* for your project when <Image> component is used.
|
|
5
|
+
* @param options - ImageLoaderOptions
|
|
6
|
+
*/
|
|
7
|
+
export default function imageLoader({ context, src }) {
|
|
8
|
+
const { buildId } = context;
|
|
9
|
+
// Add buildId to the image URL
|
|
10
|
+
if (src.includes('?'))
|
|
11
|
+
return `${src}&${buildId}`;
|
|
12
|
+
return `${src}?${buildId}`;
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -6,4 +6,6 @@ export declare function generateTemplatesCode(ssr: boolean): Promise<string>;
|
|
|
6
6
|
export declare function generateTemplateCode(template: Template): Promise<string>;
|
|
7
7
|
export declare function generateImportCode(template: Template): string;
|
|
8
8
|
export declare function generateRenderCode(ssr: boolean): Promise<string>;
|
|
9
|
+
export declare function generateImageCode(): Promise<string>;
|
|
9
10
|
export declare function getStaticImportsCode(): string;
|
|
11
|
+
export declare function getStaticImportkey(): string;
|
|
@@ -36,6 +36,7 @@ export async function generateCompileTimeContextCode(ssr) {
|
|
|
36
36
|
version: '${version}',
|
|
37
37
|
buildId: '${buildId}',
|
|
38
38
|
props: ${JSON.stringify(props)},
|
|
39
|
+
image: ${await generateImageCode()},
|
|
39
40
|
serverProps: ${JSON.stringify(ssr ? serverProps : {})},
|
|
40
41
|
headElements: ${JSON.stringify(ssr ? headElements : [])},
|
|
41
42
|
bodyElements: ${JSON.stringify(ssr ? bodyElements : [])},
|
|
@@ -84,7 +85,7 @@ export async function generateTemplateCode(template) {
|
|
|
84
85
|
export function generateImportCode(template) {
|
|
85
86
|
// Sync templates are imported statically
|
|
86
87
|
if (Object.values(SYNC_TEMPLATES).includes(template.templateType)) {
|
|
87
|
-
const key =
|
|
88
|
+
const key = getStaticImportkey();
|
|
88
89
|
staticImports.push({
|
|
89
90
|
key,
|
|
90
91
|
path: template.filename,
|
|
@@ -100,6 +101,26 @@ export async function generateRenderCode(ssr) {
|
|
|
100
101
|
return '{}';
|
|
101
102
|
return `await import("${jsx.renderFile}")`;
|
|
102
103
|
}
|
|
104
|
+
export async function generateImageCode() {
|
|
105
|
+
const { image } = await getZubyInternalConfig();
|
|
106
|
+
let loaderImport = undefined;
|
|
107
|
+
if (image?.loader) {
|
|
108
|
+
loaderImport = getStaticImportkey();
|
|
109
|
+
staticImports.push({
|
|
110
|
+
key: loaderImport,
|
|
111
|
+
path: image.loader,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return `{
|
|
115
|
+
${image?.sizes ? `sizes: ${JSON.stringify(image.sizes)},` : ''}
|
|
116
|
+
${image?.loader ? `loader: ${loaderImport},` : ''}
|
|
117
|
+
${image?.defaultFormat ? `defaultFormat: "${image.defaultFormat}",` : ''}
|
|
118
|
+
${image?.defaultQuality ? `defaultQuality: "${image.defaultQuality}",` : ''}
|
|
119
|
+
}`;
|
|
120
|
+
}
|
|
103
121
|
export function getStaticImportsCode() {
|
|
104
122
|
return staticImports.map(({ key, path }) => `import ${key} from "${path}";`).join('\n');
|
|
105
123
|
}
|
|
124
|
+
export function getStaticImportkey() {
|
|
125
|
+
return `__zuby_static_import_${staticImports.length}`;
|
|
126
|
+
}
|
|
@@ -5,11 +5,12 @@ import { performance } from 'node:perf_hooks';
|
|
|
5
5
|
import ZubyRenderer from '../../server/zubyRenderer.js';
|
|
6
6
|
import { writeFile } from 'fs/promises';
|
|
7
7
|
import { getPages } from '../../templates/index.js';
|
|
8
|
-
import { OUTPUTS } from '../../types.js';
|
|
8
|
+
import { OUTPUTS, PLUGIN_HOOKS } from '../../types.js';
|
|
9
9
|
import { PATH_TYPES } from '../../templates/types.js';
|
|
10
10
|
import { substitutePathParams } from '../../templates/pathUtils.js';
|
|
11
11
|
import { normalizePath } from '../../utils/pathUtils.js';
|
|
12
12
|
import { HTTP_HEADERS, ZUBY_USER_AGENTS } from '../../constants.js';
|
|
13
|
+
import { executePlugins } from '../../config.js';
|
|
13
14
|
/**
|
|
14
15
|
* This is internal plugin
|
|
15
16
|
* that pre-renders the pages during the build.
|
|
@@ -83,6 +84,10 @@ export default function prerenderPlugin() {
|
|
|
83
84
|
// Assign all discovered prerender paths to the config for other plugins.
|
|
84
85
|
config.prerenderPaths = prerenderPaths;
|
|
85
86
|
for (const path of prerenderPaths) {
|
|
87
|
+
// Run pre-render start hook
|
|
88
|
+
await executePlugins(config, PLUGIN_HOOKS.ZubyPrerenderStart, {
|
|
89
|
+
path,
|
|
90
|
+
});
|
|
86
91
|
const pageReq = new Request(new URL(path, reqBaseUrl), reqOptions);
|
|
87
92
|
const propsReq = new Request(new URL(`/_props${path}`, reqBaseUrl), reqOptions);
|
|
88
93
|
const [pageRes, propsRes] = await Promise.all([
|
|
@@ -104,6 +109,11 @@ export default function prerenderPlugin() {
|
|
|
104
109
|
});
|
|
105
110
|
});
|
|
106
111
|
await Promise.all([writeFile(pageTarget, page), writeFile(propsTarget, props)]);
|
|
112
|
+
// Run pre-render done hook
|
|
113
|
+
await executePlugins(config, PLUGIN_HOOKS.ZubyPrerenderDone, {
|
|
114
|
+
path,
|
|
115
|
+
body: page,
|
|
116
|
+
});
|
|
107
117
|
logger.info('[prerender] Pre-rendered path: ' + path);
|
|
108
118
|
}
|
|
109
119
|
const finishTime = performance.now();
|
package/server/index.js
CHANGED
|
@@ -2563,7 +2563,7 @@ var ZubyServer = class {
|
|
|
2563
2563
|
headers[HTTP_HEADERS.ContentLength] = (end - start + 1).toString();
|
|
2564
2564
|
headers[HTTP_HEADERS.AcceptRanges] = "bytes";
|
|
2565
2565
|
}
|
|
2566
|
-
const encoding = this.getEncoding(req);
|
|
2566
|
+
const encoding = this.shouldCompress(headers) ? this.getEncoding(req) : ENCODINGS.none;
|
|
2567
2567
|
const compressionStream = this.getCompressionStream(encoding);
|
|
2568
2568
|
if (encoding !== ENCODINGS.none) {
|
|
2569
2569
|
headers[HTTP_HEADERS.ContentEncoding] = encoding;
|
|
@@ -2576,9 +2576,9 @@ var ZubyServer = class {
|
|
|
2576
2576
|
}
|
|
2577
2577
|
async serverDirMiddleware(nodeReq, nodeRes, _next) {
|
|
2578
2578
|
const req = await this.toRequest(nodeReq);
|
|
2579
|
-
const encoding = this.getEncoding(nodeReq);
|
|
2580
2579
|
const cacheKey = new URL(req.url, "http://localhost").pathname;
|
|
2581
2580
|
const res = this.cacheRead(cacheKey) || this.cacheWrite(cacheKey, await this.renderer.render(req));
|
|
2581
|
+
const encoding = this.getEncoding(nodeReq);
|
|
2582
2582
|
return this.toNodeResponse(res, nodeRes, encoding);
|
|
2583
2583
|
}
|
|
2584
2584
|
cacheRead(key) {
|
|
@@ -2666,6 +2666,7 @@ var ZubyServer = class {
|
|
|
2666
2666
|
async toNodeResponse(res, nodeRes, encoding = ENCODINGS.none) {
|
|
2667
2667
|
const headers = {};
|
|
2668
2668
|
res.headers.forEach((value, key) => headers[key] = value);
|
|
2669
|
+
encoding = this.shouldCompress(headers) ? encoding : ENCODINGS.none;
|
|
2669
2670
|
const bodyBuffer = Buffer.from(await res.arrayBuffer());
|
|
2670
2671
|
const bodyStream = Readable.from(bodyBuffer);
|
|
2671
2672
|
const compressionStream = this.getCompressionStream(encoding);
|
|
@@ -2702,6 +2703,10 @@ var ZubyServer = class {
|
|
|
2702
2703
|
};
|
|
2703
2704
|
return compressionMap[encoding];
|
|
2704
2705
|
}
|
|
2706
|
+
shouldCompress(resHeaders) {
|
|
2707
|
+
const contentType = (resHeaders[HTTP_HEADERS.ContentType] || resHeaders[HTTP_HEADERS.ContentType.toLowerCase()] || "").toString();
|
|
2708
|
+
return contentType.startsWith("text/") || contentType.startsWith("application/json");
|
|
2709
|
+
}
|
|
2705
2710
|
};
|
|
2706
2711
|
|
|
2707
2712
|
// src/server/index.ts
|
package/server/zubyServer.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/// <reference types="node" resolution-mode="require"/>
|
|
4
4
|
import { Server as HttpsServer } from 'node:https';
|
|
5
5
|
import { Server as HttpServer, ServerResponse } from 'node:http';
|
|
6
|
-
import { ZubyServerOptions, NodeResponse, NodeRequest, ZubyMiddleware, Encoding } from './types.js';
|
|
6
|
+
import { ZubyHeaders, ZubyServerOptions, NodeResponse, NodeRequest, ZubyMiddleware, Encoding } from './types.js';
|
|
7
7
|
import { ZubyLogger } from '../logger/types.js';
|
|
8
8
|
import ZubyRenderer from './zubyRenderer.js';
|
|
9
9
|
import { PassThrough } from 'stream';
|
|
@@ -30,4 +30,5 @@ export default class ZubyServer {
|
|
|
30
30
|
reload(): Promise<void>;
|
|
31
31
|
getEncoding(nodeReq: NodeRequest): string;
|
|
32
32
|
getCompressionStream(encoding: Encoding): PassThrough;
|
|
33
|
+
shouldCompress(resHeaders: ZubyHeaders): boolean;
|
|
33
34
|
}
|
package/server/zubyServer.js
CHANGED
|
@@ -106,7 +106,8 @@ export default class ZubyServer {
|
|
|
106
106
|
headers[HTTP_HEADERS.ContentLength] = (end - start + 1).toString();
|
|
107
107
|
headers[HTTP_HEADERS.AcceptRanges] = 'bytes';
|
|
108
108
|
}
|
|
109
|
-
|
|
109
|
+
// We will compress only txt/json responses for performance reasons
|
|
110
|
+
const encoding = this.shouldCompress(headers) ? this.getEncoding(req) : ENCODINGS.none;
|
|
110
111
|
const compressionStream = this.getCompressionStream(encoding);
|
|
111
112
|
if (encoding !== ENCODINGS.none) {
|
|
112
113
|
headers[HTTP_HEADERS.ContentEncoding] = encoding;
|
|
@@ -124,9 +125,9 @@ export default class ZubyServer {
|
|
|
124
125
|
}
|
|
125
126
|
async serverDirMiddleware(nodeReq, nodeRes, _next) {
|
|
126
127
|
const req = await this.toRequest(nodeReq);
|
|
127
|
-
const encoding = this.getEncoding(nodeReq);
|
|
128
128
|
const cacheKey = new URL(req.url, 'http://localhost').pathname;
|
|
129
129
|
const res = this.cacheRead(cacheKey) || this.cacheWrite(cacheKey, await this.renderer.render(req));
|
|
130
|
+
const encoding = this.getEncoding(nodeReq);
|
|
130
131
|
return this.toNodeResponse(res, nodeRes, encoding);
|
|
131
132
|
}
|
|
132
133
|
cacheRead(key) {
|
|
@@ -220,6 +221,8 @@ export default class ZubyServer {
|
|
|
220
221
|
async toNodeResponse(res, nodeRes, encoding = ENCODINGS.none) {
|
|
221
222
|
const headers = {};
|
|
222
223
|
res.headers.forEach((value, key) => (headers[key] = value));
|
|
224
|
+
// We will compress only txt/json responses for performance reasons
|
|
225
|
+
encoding = this.shouldCompress(headers) ? encoding : ENCODINGS.none;
|
|
223
226
|
const bodyBuffer = Buffer.from(await res.arrayBuffer());
|
|
224
227
|
const bodyStream = Readable.from(bodyBuffer);
|
|
225
228
|
const compressionStream = this.getCompressionStream(encoding);
|
|
@@ -265,4 +268,10 @@ export default class ZubyServer {
|
|
|
265
268
|
};
|
|
266
269
|
return compressionMap[encoding];
|
|
267
270
|
}
|
|
271
|
+
shouldCompress(resHeaders) {
|
|
272
|
+
const contentType = (resHeaders[HTTP_HEADERS.ContentType] ||
|
|
273
|
+
resHeaders[HTTP_HEADERS.ContentType.toLowerCase()] ||
|
|
274
|
+
'').toString();
|
|
275
|
+
return contentType.startsWith('text/') || contentType.startsWith('application/json');
|
|
276
|
+
}
|
|
268
277
|
}
|
package/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { ZubyLogger } from './logger/types.js';
|
|
|
4
4
|
import ReadableStream = NodeJS.ReadableStream;
|
|
5
5
|
import { PathParamsType, Template, TemplateFile } from './templates/types.js';
|
|
6
6
|
import ZubyDevServer from './server/zubyDevServer.js';
|
|
7
|
+
import { GlobalContext } from './contexts/index.js';
|
|
7
8
|
export interface ZubyConfig {
|
|
8
9
|
/**
|
|
9
10
|
* The JSX provider which will be used to render the pages.
|
|
@@ -192,6 +193,37 @@ export interface ZubyConfig {
|
|
|
192
193
|
* @private
|
|
193
194
|
*/
|
|
194
195
|
entryScriptsBottom?: string[];
|
|
196
|
+
/**
|
|
197
|
+
* The image component options.
|
|
198
|
+
*/
|
|
199
|
+
image?: {
|
|
200
|
+
/**
|
|
201
|
+
* The path to the image loader function.
|
|
202
|
+
* @default 'zuby/imageLoader.js'
|
|
203
|
+
*/
|
|
204
|
+
loader?: string;
|
|
205
|
+
/**
|
|
206
|
+
* The array of image sizes
|
|
207
|
+
* that will be used to generate image src.
|
|
208
|
+
* Zuby.js will try to use the closest size to the actual specified size.
|
|
209
|
+
*/
|
|
210
|
+
sizes?: number[];
|
|
211
|
+
/**
|
|
212
|
+
* The default format of the image,
|
|
213
|
+
* that will be passed to the image loader function
|
|
214
|
+
* if the format is not specified.
|
|
215
|
+
* @default 'webp'
|
|
216
|
+
*/
|
|
217
|
+
defaultFormat?: ImageFormat;
|
|
218
|
+
/**
|
|
219
|
+
* The default quality of the image,
|
|
220
|
+
* that will be passed to the image loader function
|
|
221
|
+
* if the quality is not specified.
|
|
222
|
+
* This should be a number between 0 and 100.
|
|
223
|
+
* @default 75
|
|
224
|
+
*/
|
|
225
|
+
defaultQuality?: number;
|
|
226
|
+
};
|
|
195
227
|
}
|
|
196
228
|
export interface ZubyInternalConfig extends Required<ZubyConfig> {
|
|
197
229
|
/**
|
|
@@ -377,6 +409,16 @@ export interface ZubyPlugin extends VitePlugin {
|
|
|
377
409
|
* This hook is called after the server build is done
|
|
378
410
|
*/
|
|
379
411
|
'zuby:build:server:done'?: (params: ZubyBuildHookParams) => void | Promise<void>;
|
|
412
|
+
/**
|
|
413
|
+
* This hook is called for each path
|
|
414
|
+
* before the pre-rendering process starts
|
|
415
|
+
*/
|
|
416
|
+
'zuby:prerender:start'?: (params: ZubyPrerenderStartParams) => void | Promise<void>;
|
|
417
|
+
/**
|
|
418
|
+
* This hook is called for each path
|
|
419
|
+
* after the pre-rendering process ends
|
|
420
|
+
*/
|
|
421
|
+
'zuby:prerender:done'?: (params: ZubyPrerenderDoneParams) => void | Promise<void>;
|
|
380
422
|
/**
|
|
381
423
|
* This hook is called after the whole build process is done
|
|
382
424
|
*/
|
|
@@ -410,6 +452,14 @@ export interface ZubyPreviewHookParams {
|
|
|
410
452
|
config: ZubyInternalConfig;
|
|
411
453
|
logger: ZubyLogger;
|
|
412
454
|
}
|
|
455
|
+
export interface ZubyPrerenderStartParams {
|
|
456
|
+
config: ZubyInternalConfig;
|
|
457
|
+
logger: ZubyLogger;
|
|
458
|
+
path: string;
|
|
459
|
+
}
|
|
460
|
+
export interface ZubyPrerenderDoneParams extends ZubyPrerenderStartParams {
|
|
461
|
+
body: string;
|
|
462
|
+
}
|
|
413
463
|
export interface ZubyBuildHookParams {
|
|
414
464
|
config: ZubyInternalConfig;
|
|
415
465
|
logger: ZubyLogger;
|
|
@@ -430,6 +480,8 @@ export declare const PLUGIN_HOOKS: {
|
|
|
430
480
|
ZubyDevSetup: string;
|
|
431
481
|
ZubyDevStart: string;
|
|
432
482
|
ZubyPreviewStart: string;
|
|
483
|
+
ZubyPrerenderStart: string;
|
|
484
|
+
ZubyPrerenderDone: string;
|
|
433
485
|
ZubyBuildSetup: string;
|
|
434
486
|
ZubyBuildStart: string;
|
|
435
487
|
ZubyBuildClientDone: string;
|
|
@@ -437,3 +489,53 @@ export declare const PLUGIN_HOOKS: {
|
|
|
437
489
|
ZubyBuildDone: string;
|
|
438
490
|
};
|
|
439
491
|
export type PluginHook = (typeof PLUGIN_HOOKS)[keyof typeof PLUGIN_HOOKS];
|
|
492
|
+
/**
|
|
493
|
+
* The options for the ImageLoader.
|
|
494
|
+
*/
|
|
495
|
+
export interface ImageLoaderOptions {
|
|
496
|
+
/**
|
|
497
|
+
* The GlobalContext
|
|
498
|
+
*/
|
|
499
|
+
context: GlobalContext;
|
|
500
|
+
/**
|
|
501
|
+
* The path to the image file.
|
|
502
|
+
*/
|
|
503
|
+
src: string;
|
|
504
|
+
/**
|
|
505
|
+
* True if the provided src is an absolute path.
|
|
506
|
+
*/
|
|
507
|
+
isAbsolute?: boolean;
|
|
508
|
+
/**
|
|
509
|
+
* The width of the image.
|
|
510
|
+
*/
|
|
511
|
+
width?: number;
|
|
512
|
+
/**
|
|
513
|
+
* The height of the image.
|
|
514
|
+
*/
|
|
515
|
+
height?: number;
|
|
516
|
+
/**
|
|
517
|
+
* The quality of the image.
|
|
518
|
+
*/
|
|
519
|
+
quality?: number;
|
|
520
|
+
/**
|
|
521
|
+
* The format of the image.
|
|
522
|
+
*/
|
|
523
|
+
format?: ImageFormat;
|
|
524
|
+
}
|
|
525
|
+
export declare const IMAGE_FORMATS: {
|
|
526
|
+
readonly WEBP: "webp";
|
|
527
|
+
readonly JPG: "jpg";
|
|
528
|
+
readonly JPEG: "jpeg";
|
|
529
|
+
readonly PNG: "png";
|
|
530
|
+
readonly AVIF: "avif";
|
|
531
|
+
readonly GIF: "gif";
|
|
532
|
+
};
|
|
533
|
+
export declare const IMAGE_FORMATS_ARRAY: string[];
|
|
534
|
+
export type ImageFormat = (typeof IMAGE_FORMATS)[keyof typeof IMAGE_FORMATS];
|
|
535
|
+
/**
|
|
536
|
+
* The ImageLoader function that is used to
|
|
537
|
+
* generate src attribute for the image component
|
|
538
|
+
* based on the given options.
|
|
539
|
+
* @param options The options for the image loader.
|
|
540
|
+
*/
|
|
541
|
+
export type ImageLoader = (options: ImageLoaderOptions) => string;
|
package/types.js
CHANGED
|
@@ -16,6 +16,10 @@ export const PLUGIN_HOOKS = {
|
|
|
16
16
|
ZubyDevStart: 'zuby:dev:start',
|
|
17
17
|
// Preview cmd
|
|
18
18
|
ZubyPreviewStart: 'zuby:preview:start',
|
|
19
|
+
// Pre-rendering hooks
|
|
20
|
+
// called for each path
|
|
21
|
+
ZubyPrerenderStart: 'zuby:prerender:start',
|
|
22
|
+
ZubyPrerenderDone: 'zuby:prerender:done',
|
|
19
23
|
// Build cmd
|
|
20
24
|
ZubyBuildSetup: 'zuby:build:setup',
|
|
21
25
|
ZubyBuildStart: 'zuby:build:start',
|
|
@@ -23,3 +27,12 @@ export const PLUGIN_HOOKS = {
|
|
|
23
27
|
ZubyBuildServerDone: 'zuby:build:server:done',
|
|
24
28
|
ZubyBuildDone: 'zuby:build:done',
|
|
25
29
|
};
|
|
30
|
+
export const IMAGE_FORMATS = {
|
|
31
|
+
WEBP: 'webp',
|
|
32
|
+
JPG: 'jpg',
|
|
33
|
+
JPEG: 'jpeg',
|
|
34
|
+
PNG: 'png',
|
|
35
|
+
AVIF: 'avif',
|
|
36
|
+
GIF: 'gif',
|
|
37
|
+
};
|
|
38
|
+
export const IMAGE_FORMATS_ARRAY = Object.values(IMAGE_FORMATS);
|