nextjs-cms 0.9.41 → 0.10.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/dist/api/actions/pages.d.ts +4 -3
- package/dist/api/actions/pages.d.ts.map +1 -1
- package/dist/api/actions/pages.js +11 -4
- package/dist/api/trpc/root.d.ts +4 -3
- package/dist/api/trpc/root.d.ts.map +1 -1
- package/dist/api/trpc/routers/config.d.ts.map +1 -1
- package/dist/api/trpc/routers/hasItemsSection.d.ts +1 -0
- package/dist/api/trpc/routers/hasItemsSection.d.ts.map +1 -1
- package/dist/api/trpc/routers/navigation.d.ts +3 -3
- package/dist/api/trpc/server.d.ts +12 -9
- package/dist/api/trpc/server.d.ts.map +1 -1
- package/dist/cli/lib/update-sections.d.ts.map +1 -1
- package/dist/cli/lib/update-sections.js +19 -0
- package/dist/core/config/config-loader.d.ts +25 -6
- package/dist/core/config/config-loader.d.ts.map +1 -1
- package/dist/core/config/config-loader.js +9 -13
- package/dist/core/fields/photo.d.ts +80 -8
- package/dist/core/fields/photo.d.ts.map +1 -1
- package/dist/core/fields/photo.js +120 -31
- package/dist/core/fields/richText.d.ts +162 -42
- package/dist/core/fields/richText.d.ts.map +1 -1
- package/dist/core/fields/richText.js +135 -35
- package/dist/core/fields/select.d.ts +1 -1
- package/dist/core/fields/select.d.ts.map +1 -1
- package/dist/core/fields/select.js +18 -2
- package/dist/core/fields/selectMultiple.d.ts.map +1 -1
- package/dist/core/fields/selectMultiple.js +9 -0
- package/dist/core/helpers/background.d.ts +18 -0
- package/dist/core/helpers/background.d.ts.map +1 -0
- package/dist/core/helpers/background.js +18 -0
- package/dist/core/helpers/index.d.ts +5 -1
- package/dist/core/helpers/index.d.ts.map +1 -1
- package/dist/core/helpers/index.js +3 -1
- package/dist/core/helpers/watermark.d.ts +96 -0
- package/dist/core/helpers/watermark.d.ts.map +1 -0
- package/dist/core/helpers/watermark.js +61 -0
- package/dist/core/sections/category.d.ts +78 -42
- package/dist/core/sections/category.d.ts.map +1 -1
- package/dist/core/sections/hasItems.d.ts +132 -48
- package/dist/core/sections/hasItems.d.ts.map +1 -1
- package/dist/core/sections/section.d.ts +62 -25
- package/dist/core/sections/section.d.ts.map +1 -1
- package/dist/core/sections/section.js +2 -2
- package/dist/core/sections/simple.d.ts +44 -8
- package/dist/core/sections/simple.d.ts.map +1 -1
- package/dist/core/submit/gallery-order.d.ts +34 -0
- package/dist/core/submit/gallery-order.d.ts.map +1 -0
- package/dist/core/submit/gallery-order.js +50 -0
- package/dist/core/submit/submit.d.ts +8 -0
- package/dist/core/submit/submit.d.ts.map +1 -1
- package/dist/core/submit/submit.js +63 -3
- package/dist/core/types/index.d.ts +1 -0
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/translations/client.d.ts +4 -4
- package/dist/translations/server.d.ts +4 -4
- package/package.json +3 -3
|
@@ -1,20 +1,54 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
1
2
|
import type { BaseFieldConfig, FieldClientConfig } from './field.js';
|
|
2
|
-
import { Field } from './field.js';
|
|
3
3
|
import { entityKind } from '../helpers/index.js';
|
|
4
|
-
import
|
|
4
|
+
import { Field } from './field.js';
|
|
5
5
|
declare const allowImageUploadsSchema: z.ZodObject<{
|
|
6
6
|
/**
|
|
7
|
-
* The public URL
|
|
7
|
+
* The public URL template for inline photos.
|
|
8
8
|
* This url should be handled by the website app, not the NextJS-CMS app
|
|
9
9
|
* This is the URL that will be used to access the photos publicly on the website
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
|
+
* `{name}` marks where the generated filename goes, so it can sit anywhere in the URL —
|
|
12
|
+
* a path segment (`https://site.com/photos/{name}`) or a query parameter
|
|
13
|
+
* (`https://site.com/api/photo?folder=posts&name={name}`).
|
|
14
|
+
*/
|
|
15
|
+
publicURL: z.ZodURL;
|
|
16
|
+
/**
|
|
17
|
+
* Bounds applied to each inline image before it is written to disk.
|
|
18
|
+
* Defaults to {@link DEFAULT_INLINE_IMAGE_SIZE}.
|
|
19
|
+
*
|
|
20
|
+
* `fit: 'inside'` scales the image down to fit within the box, keeping its aspect ratio and
|
|
21
|
+
* never enlarging a smaller image. `fit: 'cover'` fills the box exactly, cropping the overflow.
|
|
22
|
+
* `fit: 'contain'` pads the image out to the full box with `background`.
|
|
11
23
|
*/
|
|
12
|
-
|
|
13
|
-
size: z.ZodOptional<z.ZodObject<{
|
|
24
|
+
size: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
14
25
|
width: z.ZodNumber;
|
|
15
26
|
height: z.ZodNumber;
|
|
16
|
-
|
|
17
|
-
}, z.core.$strict
|
|
27
|
+
fit: z.ZodLiteral<"inside">;
|
|
28
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
29
|
+
width: z.ZodNumber;
|
|
30
|
+
height: z.ZodNumber;
|
|
31
|
+
fit: z.ZodLiteral<"cover">;
|
|
32
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
33
|
+
width: z.ZodNumber;
|
|
34
|
+
height: z.ZodNumber;
|
|
35
|
+
fit: z.ZodLiteral<"contain">;
|
|
36
|
+
/**
|
|
37
|
+
* Falls back to `media.images.background` from the CMS config, which is transparent by
|
|
38
|
+
* default. Transparency needs an alpha-capable `format` (webp or png) — jpeg flattens it
|
|
39
|
+
* to black, so set an opaque colour when writing jpeg.
|
|
40
|
+
*/
|
|
41
|
+
background: z.ZodOptional<z.ZodObject<{
|
|
42
|
+
r: z.ZodNumber;
|
|
43
|
+
g: z.ZodNumber;
|
|
44
|
+
b: z.ZodNumber;
|
|
45
|
+
alpha: z.ZodNumber;
|
|
46
|
+
}, z.core.$strict>>;
|
|
47
|
+
}, z.core.$strict>], "fit">>;
|
|
48
|
+
/**
|
|
49
|
+
* Largest accepted inline image, measured on the decoded image rather than the base64 text.
|
|
50
|
+
* Rejected during submission, before the item is saved. Defaults to {@link DEFAULT_MAX_FILE_SIZE}.
|
|
51
|
+
*/
|
|
18
52
|
maxFileSize: z.ZodOptional<z.ZodObject<{
|
|
19
53
|
size: z.ZodNumber;
|
|
20
54
|
unit: z.ZodEnum<{
|
|
@@ -22,10 +56,6 @@ declare const allowImageUploadsSchema: z.ZodObject<{
|
|
|
22
56
|
mb: "mb";
|
|
23
57
|
}>;
|
|
24
58
|
}, z.core.$strict>>;
|
|
25
|
-
handleMethod: z.ZodOptional<z.ZodEnum<{
|
|
26
|
-
base64: "base64";
|
|
27
|
-
tempSave: "tempSave";
|
|
28
|
-
}>>;
|
|
29
59
|
/**
|
|
30
60
|
* Omit the extension of the image when saving it to disk
|
|
31
61
|
*/
|
|
@@ -46,17 +76,51 @@ declare const configSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
46
76
|
allowMedia: z.ZodLiteral<true>;
|
|
47
77
|
allowImageUploads: z.ZodOptional<z.ZodObject<{
|
|
48
78
|
/**
|
|
49
|
-
* The public URL
|
|
79
|
+
* The public URL template for inline photos.
|
|
50
80
|
* This url should be handled by the website app, not the NextJS-CMS app
|
|
51
81
|
* This is the URL that will be used to access the photos publicly on the website
|
|
52
|
-
*
|
|
82
|
+
*
|
|
83
|
+
* `{name}` marks where the generated filename goes, so it can sit anywhere in the URL —
|
|
84
|
+
* a path segment (`https://site.com/photos/{name}`) or a query parameter
|
|
85
|
+
* (`https://site.com/api/photo?folder=posts&name={name}`).
|
|
86
|
+
*/
|
|
87
|
+
publicURL: z.ZodURL;
|
|
88
|
+
/**
|
|
89
|
+
* Bounds applied to each inline image before it is written to disk.
|
|
90
|
+
* Defaults to {@link DEFAULT_INLINE_IMAGE_SIZE}.
|
|
91
|
+
*
|
|
92
|
+
* `fit: 'inside'` scales the image down to fit within the box, keeping its aspect ratio and
|
|
93
|
+
* never enlarging a smaller image. `fit: 'cover'` fills the box exactly, cropping the overflow.
|
|
94
|
+
* `fit: 'contain'` pads the image out to the full box with `background`.
|
|
53
95
|
*/
|
|
54
|
-
|
|
55
|
-
size: z.ZodOptional<z.ZodObject<{
|
|
96
|
+
size: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
56
97
|
width: z.ZodNumber;
|
|
57
98
|
height: z.ZodNumber;
|
|
58
|
-
|
|
59
|
-
}, z.core.$strict
|
|
99
|
+
fit: z.ZodLiteral<"inside">;
|
|
100
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
101
|
+
width: z.ZodNumber;
|
|
102
|
+
height: z.ZodNumber;
|
|
103
|
+
fit: z.ZodLiteral<"cover">;
|
|
104
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
105
|
+
width: z.ZodNumber;
|
|
106
|
+
height: z.ZodNumber;
|
|
107
|
+
fit: z.ZodLiteral<"contain">;
|
|
108
|
+
/**
|
|
109
|
+
* Falls back to `media.images.background` from the CMS config, which is transparent by
|
|
110
|
+
* default. Transparency needs an alpha-capable `format` (webp or png) — jpeg flattens it
|
|
111
|
+
* to black, so set an opaque colour when writing jpeg.
|
|
112
|
+
*/
|
|
113
|
+
background: z.ZodOptional<z.ZodObject<{
|
|
114
|
+
r: z.ZodNumber;
|
|
115
|
+
g: z.ZodNumber;
|
|
116
|
+
b: z.ZodNumber;
|
|
117
|
+
alpha: z.ZodNumber;
|
|
118
|
+
}, z.core.$strict>>;
|
|
119
|
+
}, z.core.$strict>], "fit">>;
|
|
120
|
+
/**
|
|
121
|
+
* Largest accepted inline image, measured on the decoded image rather than the base64 text.
|
|
122
|
+
* Rejected during submission, before the item is saved. Defaults to {@link DEFAULT_MAX_FILE_SIZE}.
|
|
123
|
+
*/
|
|
60
124
|
maxFileSize: z.ZodOptional<z.ZodObject<{
|
|
61
125
|
size: z.ZodNumber;
|
|
62
126
|
unit: z.ZodEnum<{
|
|
@@ -64,10 +128,6 @@ declare const configSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
64
128
|
mb: "mb";
|
|
65
129
|
}>;
|
|
66
130
|
}, z.core.$strict>>;
|
|
67
|
-
handleMethod: z.ZodOptional<z.ZodEnum<{
|
|
68
|
-
base64: "base64";
|
|
69
|
-
tempSave: "tempSave";
|
|
70
|
-
}>>;
|
|
71
131
|
/**
|
|
72
132
|
* Omit the extension of the image when saving it to disk
|
|
73
133
|
*/
|
|
@@ -144,17 +204,51 @@ declare const optionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
144
204
|
allowMedia: z.ZodLiteral<true>;
|
|
145
205
|
allowImageUploads: z.ZodOptional<z.ZodObject<{
|
|
146
206
|
/**
|
|
147
|
-
* The public URL
|
|
207
|
+
* The public URL template for inline photos.
|
|
148
208
|
* This url should be handled by the website app, not the NextJS-CMS app
|
|
149
209
|
* This is the URL that will be used to access the photos publicly on the website
|
|
150
|
-
*
|
|
210
|
+
*
|
|
211
|
+
* `{name}` marks where the generated filename goes, so it can sit anywhere in the URL —
|
|
212
|
+
* a path segment (`https://site.com/photos/{name}`) or a query parameter
|
|
213
|
+
* (`https://site.com/api/photo?folder=posts&name={name}`).
|
|
151
214
|
*/
|
|
152
|
-
|
|
153
|
-
|
|
215
|
+
publicURL: z.ZodURL;
|
|
216
|
+
/**
|
|
217
|
+
* Bounds applied to each inline image before it is written to disk.
|
|
218
|
+
* Defaults to {@link DEFAULT_INLINE_IMAGE_SIZE}.
|
|
219
|
+
*
|
|
220
|
+
* `fit: 'inside'` scales the image down to fit within the box, keeping its aspect ratio and
|
|
221
|
+
* never enlarging a smaller image. `fit: 'cover'` fills the box exactly, cropping the overflow.
|
|
222
|
+
* `fit: 'contain'` pads the image out to the full box with `background`.
|
|
223
|
+
*/
|
|
224
|
+
size: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
154
225
|
width: z.ZodNumber;
|
|
155
226
|
height: z.ZodNumber;
|
|
156
|
-
|
|
157
|
-
}, z.core.$strict
|
|
227
|
+
fit: z.ZodLiteral<"inside">;
|
|
228
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
229
|
+
width: z.ZodNumber;
|
|
230
|
+
height: z.ZodNumber;
|
|
231
|
+
fit: z.ZodLiteral<"cover">;
|
|
232
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
233
|
+
width: z.ZodNumber;
|
|
234
|
+
height: z.ZodNumber;
|
|
235
|
+
fit: z.ZodLiteral<"contain">;
|
|
236
|
+
/**
|
|
237
|
+
* Falls back to `media.images.background` from the CMS config, which is transparent by
|
|
238
|
+
* default. Transparency needs an alpha-capable `format` (webp or png) — jpeg flattens it
|
|
239
|
+
* to black, so set an opaque colour when writing jpeg.
|
|
240
|
+
*/
|
|
241
|
+
background: z.ZodOptional<z.ZodObject<{
|
|
242
|
+
r: z.ZodNumber;
|
|
243
|
+
g: z.ZodNumber;
|
|
244
|
+
b: z.ZodNumber;
|
|
245
|
+
alpha: z.ZodNumber;
|
|
246
|
+
}, z.core.$strict>>;
|
|
247
|
+
}, z.core.$strict>], "fit">>;
|
|
248
|
+
/**
|
|
249
|
+
* Largest accepted inline image, measured on the decoded image rather than the base64 text.
|
|
250
|
+
* Rejected during submission, before the item is saved. Defaults to {@link DEFAULT_MAX_FILE_SIZE}.
|
|
251
|
+
*/
|
|
158
252
|
maxFileSize: z.ZodOptional<z.ZodObject<{
|
|
159
253
|
size: z.ZodNumber;
|
|
160
254
|
unit: z.ZodEnum<{
|
|
@@ -162,10 +256,6 @@ declare const optionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
162
256
|
mb: "mb";
|
|
163
257
|
}>;
|
|
164
258
|
}, z.core.$strict>>;
|
|
165
|
-
handleMethod: z.ZodOptional<z.ZodEnum<{
|
|
166
|
-
base64: "base64";
|
|
167
|
-
tempSave: "tempSave";
|
|
168
|
-
}>>;
|
|
169
259
|
/**
|
|
170
260
|
* Omit the extension of the image when saving it to disk
|
|
171
261
|
*/
|
|
@@ -210,17 +300,51 @@ declare const richTextFieldConfigSchema: z.ZodIntersection<z.ZodDiscriminatedUni
|
|
|
210
300
|
allowMedia: z.ZodLiteral<true>;
|
|
211
301
|
allowImageUploads: z.ZodOptional<z.ZodObject<{
|
|
212
302
|
/**
|
|
213
|
-
* The public URL
|
|
303
|
+
* The public URL template for inline photos.
|
|
214
304
|
* This url should be handled by the website app, not the NextJS-CMS app
|
|
215
305
|
* This is the URL that will be used to access the photos publicly on the website
|
|
216
|
-
*
|
|
306
|
+
*
|
|
307
|
+
* `{name}` marks where the generated filename goes, so it can sit anywhere in the URL —
|
|
308
|
+
* a path segment (`https://site.com/photos/{name}`) or a query parameter
|
|
309
|
+
* (`https://site.com/api/photo?folder=posts&name={name}`).
|
|
310
|
+
*/
|
|
311
|
+
publicURL: z.ZodURL;
|
|
312
|
+
/**
|
|
313
|
+
* Bounds applied to each inline image before it is written to disk.
|
|
314
|
+
* Defaults to {@link DEFAULT_INLINE_IMAGE_SIZE}.
|
|
315
|
+
*
|
|
316
|
+
* `fit: 'inside'` scales the image down to fit within the box, keeping its aspect ratio and
|
|
317
|
+
* never enlarging a smaller image. `fit: 'cover'` fills the box exactly, cropping the overflow.
|
|
318
|
+
* `fit: 'contain'` pads the image out to the full box with `background`.
|
|
217
319
|
*/
|
|
218
|
-
|
|
219
|
-
size: z.ZodOptional<z.ZodObject<{
|
|
320
|
+
size: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
220
321
|
width: z.ZodNumber;
|
|
221
322
|
height: z.ZodNumber;
|
|
222
|
-
|
|
223
|
-
}, z.core.$strict
|
|
323
|
+
fit: z.ZodLiteral<"inside">;
|
|
324
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
325
|
+
width: z.ZodNumber;
|
|
326
|
+
height: z.ZodNumber;
|
|
327
|
+
fit: z.ZodLiteral<"cover">;
|
|
328
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
329
|
+
width: z.ZodNumber;
|
|
330
|
+
height: z.ZodNumber;
|
|
331
|
+
fit: z.ZodLiteral<"contain">;
|
|
332
|
+
/**
|
|
333
|
+
* Falls back to `media.images.background` from the CMS config, which is transparent by
|
|
334
|
+
* default. Transparency needs an alpha-capable `format` (webp or png) — jpeg flattens it
|
|
335
|
+
* to black, so set an opaque colour when writing jpeg.
|
|
336
|
+
*/
|
|
337
|
+
background: z.ZodOptional<z.ZodObject<{
|
|
338
|
+
r: z.ZodNumber;
|
|
339
|
+
g: z.ZodNumber;
|
|
340
|
+
b: z.ZodNumber;
|
|
341
|
+
alpha: z.ZodNumber;
|
|
342
|
+
}, z.core.$strict>>;
|
|
343
|
+
}, z.core.$strict>], "fit">>;
|
|
344
|
+
/**
|
|
345
|
+
* Largest accepted inline image, measured on the decoded image rather than the base64 text.
|
|
346
|
+
* Rejected during submission, before the item is saved. Defaults to {@link DEFAULT_MAX_FILE_SIZE}.
|
|
347
|
+
*/
|
|
224
348
|
maxFileSize: z.ZodOptional<z.ZodObject<{
|
|
225
349
|
size: z.ZodNumber;
|
|
226
350
|
unit: z.ZodEnum<{
|
|
@@ -228,10 +352,6 @@ declare const richTextFieldConfigSchema: z.ZodIntersection<z.ZodDiscriminatedUni
|
|
|
228
352
|
mb: "mb";
|
|
229
353
|
}>;
|
|
230
354
|
}, z.core.$strict>>;
|
|
231
|
-
handleMethod: z.ZodOptional<z.ZodEnum<{
|
|
232
|
-
base64: "base64";
|
|
233
|
-
tempSave: "tempSave";
|
|
234
|
-
}>>;
|
|
235
355
|
/**
|
|
236
356
|
* Omit the extension of the image when saving it to disk
|
|
237
357
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"richText.d.ts","sourceRoot":"","sources":["../../../src/core/fields/richText.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"richText.d.ts","sourceRoot":"","sources":["../../../src/core/fields/richText.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,39 +1,113 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { and, eq, sql } from 'drizzle-orm';
|
|
4
4
|
import { customAlphabet } from 'nanoid';
|
|
5
5
|
import sharp from 'sharp';
|
|
6
|
-
import
|
|
6
|
+
import * as z from 'zod';
|
|
7
7
|
import { db } from '../../db/client.js';
|
|
8
8
|
import { EditorPhotosTable } from '../../db/schema.js';
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
9
|
+
import getString from '../../translations/index.js';
|
|
10
|
+
import { humanReadableFileSize } from '../../utils/index.js';
|
|
11
11
|
import { getCMSConfig } from '../config/index.js';
|
|
12
|
+
import { backgroundSchema, entityKind } from '../helpers/index.js';
|
|
12
13
|
import { sanitizeRichText } from '../security/dom.js';
|
|
14
|
+
import { baseFieldConfigSchema, Field } from './field.js';
|
|
13
15
|
const positiveInt = z.number().int().positive();
|
|
14
16
|
const nonNegativeInt = z.number().int().nonnegative();
|
|
17
|
+
/**
|
|
18
|
+
* Bounds each inline image is fitted into, discriminated on `fit` so `background` only exists
|
|
19
|
+
* where it means something. Mirrors the `fit` vocabulary of the photo field, using sharp's own
|
|
20
|
+
* names so the behaviour is not renamed in translation.
|
|
21
|
+
*/
|
|
22
|
+
const inlineImageSizeSchema = z.discriminatedUnion('fit', [
|
|
23
|
+
z.strictObject({
|
|
24
|
+
width: positiveInt,
|
|
25
|
+
height: positiveInt,
|
|
26
|
+
fit: z.literal('inside').describe('Scale down to fit within the box, keeping aspect ratio (sharp fit: inside)'),
|
|
27
|
+
}),
|
|
28
|
+
z.strictObject({
|
|
29
|
+
width: positiveInt,
|
|
30
|
+
height: positiveInt,
|
|
31
|
+
fit: z.literal('cover').describe('Crop to fill dimensions (sharp fit: cover)'),
|
|
32
|
+
}),
|
|
33
|
+
z.strictObject({
|
|
34
|
+
width: positiveInt,
|
|
35
|
+
height: positiveInt,
|
|
36
|
+
fit: z.literal('contain').describe('Pad with background to fill dimensions (sharp fit: contain)'),
|
|
37
|
+
/**
|
|
38
|
+
* Falls back to `media.images.background` from the CMS config, which is transparent by
|
|
39
|
+
* default. Transparency needs an alpha-capable `format` (webp or png) — jpeg flattens it
|
|
40
|
+
* to black, so set an opaque colour when writing jpeg.
|
|
41
|
+
*/
|
|
42
|
+
background: backgroundSchema.optional().describe('Background color for padding'),
|
|
43
|
+
}),
|
|
44
|
+
]);
|
|
45
|
+
/**
|
|
46
|
+
* Bounds every inline image is fitted into unless the field overrides `size`.
|
|
47
|
+
* 1200x675 is 16:9 at a width that covers typical article body content, scaled down to fit so a
|
|
48
|
+
* body image is never cropped or padded unless the field asks for it.
|
|
49
|
+
*/
|
|
50
|
+
const DEFAULT_INLINE_IMAGE_SIZE = {
|
|
51
|
+
width: 1200,
|
|
52
|
+
height: 675,
|
|
53
|
+
fit: 'inside',
|
|
54
|
+
};
|
|
55
|
+
/** Largest accepted inline image unless the field overrides `maxFileSize`. */
|
|
56
|
+
const DEFAULT_MAX_FILE_SIZE = { size: 1, unit: 'mb' };
|
|
57
|
+
const BYTES_PER_UNIT = { kb: 1024, mb: 1024 * 1024 };
|
|
58
|
+
/**
|
|
59
|
+
* Decoded byte length of a base64 payload, without allocating the buffer — inline images are
|
|
60
|
+
* rejected before anything is decoded or written.
|
|
61
|
+
*/
|
|
62
|
+
function base64ByteLength(base64) {
|
|
63
|
+
const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;
|
|
64
|
+
return Math.floor((base64.length * 3) / 4) - padding;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Matches the `{name}` placeholder (whitespace tolerated: `{ name }`).
|
|
68
|
+
*
|
|
69
|
+
* Built on demand rather than shared as a single global regex: a `/g` regex is stateful via
|
|
70
|
+
* `lastIndex`, so reusing one instance across `test()` calls silently alternates its result.
|
|
71
|
+
*/
|
|
72
|
+
const NAME_PLACEHOLDER = String.raw `\{\s*name\s*\}`;
|
|
73
|
+
const hasNamePlaceholder = (value) => new RegExp(NAME_PLACEHOLDER).test(value);
|
|
74
|
+
const resolvePublicURL = (template, name) => template.replace(new RegExp(NAME_PLACEHOLDER, 'g'), name);
|
|
15
75
|
const allowImageUploadsSchema = z.strictObject({
|
|
16
76
|
/**
|
|
17
|
-
* The public URL
|
|
77
|
+
* The public URL template for inline photos.
|
|
18
78
|
* This url should be handled by the website app, not the NextJS-CMS app
|
|
19
79
|
* This is the URL that will be used to access the photos publicly on the website
|
|
20
|
-
*
|
|
80
|
+
*
|
|
81
|
+
* `{name}` marks where the generated filename goes, so it can sit anywhere in the URL —
|
|
82
|
+
* a path segment (`https://site.com/photos/{name}`) or a query parameter
|
|
83
|
+
* (`https://site.com/api/photo?folder=posts&name={name}`).
|
|
21
84
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
height: positiveInt,
|
|
27
|
-
crop: z.boolean().default(false),
|
|
85
|
+
publicURL: z
|
|
86
|
+
.url()
|
|
87
|
+
.refine(hasNamePlaceholder, {
|
|
88
|
+
message: 'publicURL must contain the {name} placeholder, e.g. https://site.com/photos/{name}',
|
|
28
89
|
})
|
|
29
|
-
.
|
|
90
|
+
.describe('The public URL template for inline photos; {name} is replaced with the generated filename'),
|
|
91
|
+
/**
|
|
92
|
+
* Bounds applied to each inline image before it is written to disk.
|
|
93
|
+
* Defaults to {@link DEFAULT_INLINE_IMAGE_SIZE}.
|
|
94
|
+
*
|
|
95
|
+
* `fit: 'inside'` scales the image down to fit within the box, keeping its aspect ratio and
|
|
96
|
+
* never enlarging a smaller image. `fit: 'cover'` fills the box exactly, cropping the overflow.
|
|
97
|
+
* `fit: 'contain'` pads the image out to the full box with `background`.
|
|
98
|
+
*/
|
|
99
|
+
size: inlineImageSizeSchema.optional(),
|
|
100
|
+
/**
|
|
101
|
+
* Largest accepted inline image, measured on the decoded image rather than the base64 text.
|
|
102
|
+
* Rejected during submission, before the item is saved. Defaults to {@link DEFAULT_MAX_FILE_SIZE}.
|
|
103
|
+
*/
|
|
30
104
|
maxFileSize: z
|
|
31
105
|
.strictObject({
|
|
32
106
|
size: positiveInt,
|
|
33
107
|
unit: z.enum(['kb', 'mb']),
|
|
34
108
|
})
|
|
35
109
|
.optional(),
|
|
36
|
-
handleMethod: z.enum(['base64', 'tempSave']).optional(),
|
|
110
|
+
// handleMethod: z.enum(['base64', 'tempSave']).optional(),
|
|
37
111
|
/**
|
|
38
112
|
* Omit the extension of the image when saving it to disk
|
|
39
113
|
*/
|
|
@@ -96,13 +170,13 @@ export class RichTextField extends Field {
|
|
|
96
170
|
this.placeholder = config.placeholder;
|
|
97
171
|
this.sanitize = config.sanitize ?? true;
|
|
98
172
|
this.rtl = config.rtl;
|
|
99
|
-
if (config.allowMedia && config.allowImageUploads?.
|
|
173
|
+
if (config.allowMedia && config.allowImageUploads?.publicURL) {
|
|
100
174
|
this.allowMedia = true;
|
|
101
175
|
this.allowImageUploads = {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
176
|
+
// handleMethod: config.allowImageUploads.handleMethod ?? 'base64',
|
|
177
|
+
publicURL: config.allowImageUploads.publicURL,
|
|
178
|
+
size: config.allowImageUploads.size ?? DEFAULT_INLINE_IMAGE_SIZE,
|
|
179
|
+
maxFileSize: config.allowImageUploads.maxFileSize ?? DEFAULT_MAX_FILE_SIZE,
|
|
106
180
|
omitExtension: config.allowImageUploads.omitExtension ?? true,
|
|
107
181
|
format: config.allowImageUploads.format ?? 'webp',
|
|
108
182
|
};
|
|
@@ -164,9 +238,24 @@ export class RichTextField extends Field {
|
|
|
164
238
|
return;
|
|
165
239
|
const regex = /<img.*?src="(data:image\/.*?;base64,.*?)".*?>/g;
|
|
166
240
|
const matches = this.value.matchAll(regex);
|
|
241
|
+
const maxFileSize = this.allowImageUploads.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
242
|
+
const maxBytes = maxFileSize.size * BYTES_PER_UNIT[maxFileSize.unit];
|
|
167
243
|
for (const match of matches) {
|
|
168
244
|
const base64String = match[1];
|
|
169
245
|
const extension = base64String.split(';')[0].split('/')[1];
|
|
246
|
+
/**
|
|
247
|
+
* Reject oversized images here rather than in `writeInlineImages`: extraction runs
|
|
248
|
+
* during submission, so throwing prevents the item from being saved at all, whereas
|
|
249
|
+
* the write step runs afterwards and the row would already exist.
|
|
250
|
+
*/
|
|
251
|
+
const byteLength = base64ByteLength(base64String.split(',')[1] ?? '');
|
|
252
|
+
if (byteLength > maxBytes) {
|
|
253
|
+
throw new Error(getString('fileSizeExceedsMax', this.language, {
|
|
254
|
+
field: this.getLocalizedLabel(),
|
|
255
|
+
actual: humanReadableFileSize(byteLength),
|
|
256
|
+
max: `${maxFileSize.size} ${maxFileSize.unit}`,
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
170
259
|
const randomString = customAlphabet('1234567890abcdef', 21)();
|
|
171
260
|
const name = `${randomString}${this.allowImageUploads.omitExtension ? '' : `.${extension}`}`;
|
|
172
261
|
this._inlinePhotos.push({
|
|
@@ -175,9 +264,9 @@ export class RichTextField extends Field {
|
|
|
175
264
|
name: name,
|
|
176
265
|
});
|
|
177
266
|
/**
|
|
178
|
-
* Replace the inline image src with the
|
|
267
|
+
* Replace the inline image src with the public URL of the image
|
|
179
268
|
*/
|
|
180
|
-
this.value = this.value.replace(base64String,
|
|
269
|
+
this.value = this.value.replace(base64String, resolvePublicURL(this.allowImageUploads.publicURL, name));
|
|
181
270
|
}
|
|
182
271
|
}
|
|
183
272
|
async writeInlineImages(sectionName, itemId, locale) {
|
|
@@ -203,7 +292,20 @@ export class RichTextField extends Field {
|
|
|
203
292
|
sharp.cache({ files: 0 });
|
|
204
293
|
sharp.cache(false);
|
|
205
294
|
const image = sharp(buffer);
|
|
295
|
+
const size = this.allowImageUploads.size ?? DEFAULT_INLINE_IMAGE_SIZE;
|
|
206
296
|
await image
|
|
297
|
+
.resize({
|
|
298
|
+
width: size.width,
|
|
299
|
+
height: size.height,
|
|
300
|
+
fit: size.fit,
|
|
301
|
+
// `inside` only ever scales down — enlarging a smaller image to fill the box
|
|
302
|
+
// would cost quality for nothing. `cover` and `contain` produce the exact box,
|
|
303
|
+
// so they are allowed to enlarge.
|
|
304
|
+
withoutEnlargement: size.fit === 'inside',
|
|
305
|
+
...(size.fit === 'contain'
|
|
306
|
+
? { background: size.background ?? cmsConfig.media.images.background }
|
|
307
|
+
: {}),
|
|
308
|
+
})
|
|
207
309
|
.toFormat(this.allowImageUploads.format ?? 'webp')
|
|
208
310
|
.toFile(path.join(uploadsFolder, '.photos', sectionName, photo.name));
|
|
209
311
|
/**
|
|
@@ -237,7 +339,7 @@ export class RichTextField extends Field {
|
|
|
237
339
|
/**
|
|
238
340
|
* Sanitize the value
|
|
239
341
|
*/
|
|
240
|
-
this.sanitizeValue();
|
|
342
|
+
await this.sanitizeValue();
|
|
241
343
|
if (!this.value)
|
|
242
344
|
return;
|
|
243
345
|
/**
|
|
@@ -291,19 +393,17 @@ export class RichTextField extends Field {
|
|
|
291
393
|
if (tablePhotos.length === 0)
|
|
292
394
|
return;
|
|
293
395
|
/**
|
|
294
|
-
*
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Check if the photos in the database are still present in the value
|
|
396
|
+
* Check if the photos in the database are still present in the value.
|
|
397
|
+
*
|
|
398
|
+
* Matched on the generated filename rather than the full public URL: the name is a unique
|
|
399
|
+
* random token, while the URL is presentation. It can be re-encoded by the sanitizer
|
|
400
|
+
* (`&` -> `&`), or change wholesale when `publicURL` or the site's domain changes —
|
|
401
|
+
* none of which mean the admin removed the image. A stale match here deletes a file that
|
|
402
|
+
* is still in use, so the check errs towards keeping (an orphan file is recoverable, a
|
|
403
|
+
* deleted one is not).
|
|
304
404
|
*/
|
|
305
405
|
for (const tablePhoto of tablePhotos) {
|
|
306
|
-
if (!
|
|
406
|
+
if (!this.value.includes(tablePhoto.name)) {
|
|
307
407
|
/**
|
|
308
408
|
* Delete the photo from the database
|
|
309
409
|
*/
|
|
@@ -379,8 +379,8 @@ declare const selectFieldConfigSchema: z.ZodIntersection<z.ZodUnion<readonly [z.
|
|
|
379
379
|
}, z.core.$strict>]>, z.ZodObject<{
|
|
380
380
|
type: z.ZodLiteral<"select">;
|
|
381
381
|
optionsType: z.ZodEnum<{
|
|
382
|
-
section: "section";
|
|
383
382
|
db: "db";
|
|
383
|
+
section: "section";
|
|
384
384
|
static: "static";
|
|
385
385
|
}>;
|
|
386
386
|
build: z.ZodFunction<z.core.$ZodFunctionArgs, z.ZodCustom<SelectField, SelectField>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/core/fields/select.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,KAAK,EAAE,eAAe,EAAyB,eAAe,EAAyB,MAAM,aAAa,CAAA;AACjH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAyB,KAAK,EAAE,MAAM,YAAY,CAAA;AAEzD,eAAO,MAAM,kBAAkB;;;kBAG7B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D,eAAO,MAAM,8BAA8B;;IAEvC;;OAEG;;IAEH;;OAEG;;kBAEL,CAAA;AAEF,KAAK,mBAAmB,GAAG;IACvB,IAAI,EAAE,WAAW,GAAG,UAAU,CAAA;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,IAAI,eAAe,GAAG,eAAe,CAAA;CAC7C,CAAA;AAyCD,eAAO,MAAM,+BAA+B;;;QAxDxC;;WAEG;;QAEH;;WAEG;;;;;;;;;;;;;;;;;;;;;;;QANH;;WAEG;;QAEH;;WAEG;;;;;;;;;;;;;QANH;;WAEG;;QAEH;;WAEG;;;;;;;;;;oBAsDL,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAE/E,qBAAa,WAAY,SAAQ,KAAK,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAC/D,gBAAyB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAgB;IAC7D,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAA;IACjD,QAAQ,CAAC,EAAE,EAAE;QACT,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;QAClC,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,SAAkB,aAAa,CAAC,EAC1B;QACI,KAAK,EAAE,MAAM,CAAA;QACb,cAAc,EAAE,MAAM,CAAA;QACtB,gBAAgB,EAAE,MAAM,CAAA;KAC3B,GACD,SAAS,CAAY;IAClB,KAAK,EAAE,YAAY,EAAE,GAAG,SAAS,CAAY;IAEtD,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,CAAA;IACjD,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,EAAE,YAAY,EAAE,GAAG,SAAS,CAAA;IACnC,OAAO,CAAC,WAAW,CAA4B;gBACnC,MAAM,EAAE,eAAe,CAAC,iBAAiB,CAAC;IAyDtD;;;;OAIG;IACM,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,EAAE,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/core/fields/select.ts"],"names":[],"mappings":"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"}
|
|
@@ -144,9 +144,14 @@ export class SelectField extends Field {
|
|
|
144
144
|
*/
|
|
145
145
|
if (typeof value === 'string' || typeof value === 'number') {
|
|
146
146
|
/**
|
|
147
|
-
* Split the values by comma and set the value as an array of objects
|
|
147
|
+
* Split the values by comma and set the value as an array of objects.
|
|
148
|
+
* Empty segments are dropped — '' is never a valid option value, and
|
|
149
|
+
* an unset select posts exactly that.
|
|
148
150
|
*/
|
|
149
|
-
const values = value
|
|
151
|
+
const values = value
|
|
152
|
+
.toString()
|
|
153
|
+
.split(',')
|
|
154
|
+
.filter((value) => value !== '');
|
|
150
155
|
this.value = [];
|
|
151
156
|
values.map((value) => {
|
|
152
157
|
if (this.checkValueExists) {
|
|
@@ -176,6 +181,17 @@ export class SelectField extends Field {
|
|
|
176
181
|
else {
|
|
177
182
|
this.value = undefined;
|
|
178
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Nothing resolved to a real option — either the select was left empty
|
|
186
|
+
* (`Submit.setFieldValue` hands us `[]` for an untouched select) or
|
|
187
|
+
* `checkValueExists` dropped everything submitted. Represent that as
|
|
188
|
+
* "no value" rather than an empty array: an empty array would join into
|
|
189
|
+
* '' in `getSubmitValue()`, and an INSERT writes that verbatim, which
|
|
190
|
+
* MySQL rejects for int and enum columns.
|
|
191
|
+
*/
|
|
192
|
+
if (this.value?.length === 0) {
|
|
193
|
+
this.value = undefined;
|
|
194
|
+
}
|
|
179
195
|
}
|
|
180
196
|
hasSqlNameAndValue() {
|
|
181
197
|
return this.destinationDb === undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selectMultiple.d.ts","sourceRoot":"","sources":["../../../src/core/fields/selectMultiple.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAyB,KAAK,EAAE,MAAM,YAAY,CAAA;AAsDzD,QAAA,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAdnB,WAAW,GAAG,UAAU;cACxB,MAAM;gBACJ,MAAM;iBACL,eAAe,GAAG,eAAe;;cAHpC,WAAW,GAAG,UAAU;cACxB,MAAM;gBACJ,MAAM;iBACL,eAAe,GAAG,eAAe;;;;;;;;;;;;;;;oBAepD,CAAA;AAEF,KAAK,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAEhF,qBAAa,mBAAoB,SAAQ,KAAK,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;IACxF,gBAAyB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAwB;IACrE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAA;IACjD,QAAQ,CAAC,EAAE,EAAE;QACT,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;QAClC,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;IACa,OAAO,EAAE,YAAY,EAAE,GAAG,SAAS,CAAA;IACjD,SAAkB,aAAa,CAAC,EAAE;QAC9B,KAAK,EAAE,MAAM,CAAA;QACb,cAAc,EAAE,MAAM,CAAA;QACtB,gBAAgB,EAAE,MAAM,CAAA;KAC3B,CAAA;IACQ,KAAK,EAAE,YAAY,EAAE,GAAG,SAAS,CAAY;IAEtD,OAAO,CAAC,eAAe,CAAoB;gBAC/B,MAAM,EAAE,eAAe,CAAC,yBAAyB,CAAC;IAyD9D,MAAM,CAAC,aAAa,IAAI,MAAM;IAId,kBAAkB,IAAI,OAAO;IAI7C;;OAEG;IACH,QAAQ;;;;IAIR;;OAEG;IACM,cAAc,IAAI,MAAM,GAAG,YAAY,EAAE,GAAG,SAAS;IAQ9D;;;;OAIG;IACM,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"selectMultiple.d.ts","sourceRoot":"","sources":["../../../src/core/fields/selectMultiple.ts"],"names":[],"mappings":"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"}
|
|
@@ -192,6 +192,15 @@ export class SelectMultipleField extends Field {
|
|
|
192
192
|
else {
|
|
193
193
|
this.value = value;
|
|
194
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Nothing resolved to a real option — the field was left empty, or every
|
|
197
|
+
* submitted value was dropped. Represent that as "no value" rather than an
|
|
198
|
+
* empty array: an empty array would join into '' in `getSubmitValue()`, and
|
|
199
|
+
* an INSERT writes that verbatim, which MySQL rejects for int columns.
|
|
200
|
+
*/
|
|
201
|
+
if (this.value?.length === 0) {
|
|
202
|
+
this.value = undefined;
|
|
203
|
+
}
|
|
195
204
|
}
|
|
196
205
|
exportForClient() {
|
|
197
206
|
return {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Padding colour schema — shared by every field that resizes images, so the shape stays
|
|
4
|
+
* identical across them. Only meaningful alongside `fit: 'contain'`, where the image is padded
|
|
5
|
+
* out to the full box; fields fall back to `media.images.background` from the CMS config when
|
|
6
|
+
* it is omitted.
|
|
7
|
+
*
|
|
8
|
+
* `alpha: 0` only survives in formats with an alpha channel (webp, png). Encoding transparent
|
|
9
|
+
* padding to jpeg flattens it to black, so pick an opaque colour for jpeg output.
|
|
10
|
+
*/
|
|
11
|
+
export declare const backgroundSchema: z.ZodObject<{
|
|
12
|
+
r: z.ZodNumber;
|
|
13
|
+
g: z.ZodNumber;
|
|
14
|
+
b: z.ZodNumber;
|
|
15
|
+
alpha: z.ZodNumber;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
export type Background = z.infer<typeof backgroundSchema>;
|
|
18
|
+
//# sourceMappingURL=background.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../../src/core/helpers/background.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB;;;;;kBAO+C,CAAA;AAE5E,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA"}
|