feat: support external and step images with structured cooking instructions
This commit is contained in:
1 parent
361862ad0b
commit
0ec1d45bdb
34 files changed
+898
-92
No files matched your search
+14
-9
@@ -8,6 +8,16 @@ const text = (max: number) =>
|
||||
.refine((v) => !/<\/?[a-z][^>]*>/i.test(v), 'HTML ist nicht erlaubt.');
|
||||
const id = z.string().regex(/^[a-zA-Z0-9_-]{1,80}$/);
|
||||
export const units = ['g', 'kg', 'ml', 'l', 'Stück', 'TL', 'EL', 'Prise', 'Bund', ''] as const;
|
||||
export const imageSchema = z.union(
|
||||
[
|
||||
z.string().regex(/^\/(?:media\/[a-f0-9-]+\.webp|images\/[a-z0-9-]+\.(?:webp|jpg|svg))$/),
|
||||
z
|
||||
.url({ protocol: /^https$/ })
|
||||
.max(2048)
|
||||
.regex(/^https:\/\/[^@\s/\\]+(?:[/?#][^\s\\]*)?$/i),
|
||||
],
|
||||
{ error: 'Bitte einen lokalen Bildpfad oder eine vollständige HTTPS-Bildadresse verwenden.' },
|
||||
);
|
||||
export const ingredientSchema = z.object({
|
||||
id,
|
||||
name: text(160).min(1, 'Zutat benötigt einen Namen.'),
|
||||
@@ -22,25 +32,20 @@ export const stepSchema = z.object({
|
||||
title: text(160).default(''),
|
||||
text: text(6000).min(1, 'Schritt benötigt eine Anleitung.'),
|
||||
ingredients: z.array(id).max(100).default([]),
|
||||
images: z.array(imageSchema).max(10).default([]),
|
||||
timers: z
|
||||
.array(z.object({ id, label: text(100).min(1), seconds: z.number().int().min(1).max(172800) }))
|
||||
.max(10)
|
||||
.default([]),
|
||||
});
|
||||
const image = z
|
||||
.string()
|
||||
.regex(
|
||||
/^\/(?:media\/[a-f0-9-]+\.webp|images\/[a-z0-9-]+\.(?:webp|jpg|svg))$/,
|
||||
'Nur lokale Bilder sind erlaubt.',
|
||||
);
|
||||
export const recipeSchema = z
|
||||
.object({
|
||||
id: z.string().uuid().optional(),
|
||||
title: text(180).min(2, 'Titel: mindestens 2 Zeichen.'),
|
||||
subtitle: text(200).default(''),
|
||||
description: text(4000).default(''),
|
||||
image: image.or(z.literal('')).default(''),
|
||||
images: z.array(image).max(20).default([]),
|
||||
image: imageSchema.or(z.literal('')).default(''),
|
||||
images: z.array(imageSchema).max(20).default([]),
|
||||
categories: z.array(text(60).min(1)).max(20).default([]),
|
||||
tags: z.array(text(60).min(1)).max(30).default([]),
|
||||
cuisine: text(80).default(''),
|
||||
@@ -128,7 +133,7 @@ export function emptyRecipe(): Recipe {
|
||||
ingredients: [
|
||||
{ id: 'i1', name: '', amount: null, unit: 'g', section: '', note: '', optional: false },
|
||||
],
|
||||
steps: [{ id: 's1', title: '', text: '', ingredients: [], timers: [] }],
|
||||
steps: [{ id: 's1', title: '', text: '', ingredients: [], images: [], timers: [] }],
|
||||
tips: '',
|
||||
storage: '',
|
||||
nutrition: null,
|
||||
|
||||
Reference in new issue
Block a user