Compare commits

...

8 Commits

Author SHA1 Message Date
mealie-commit-bot[bot]
70b5865dce chore: bump version to v3.9.2 2026-01-02 19:40:19 +00:00
Michael Genson
3be7056f2c fix: Exception handling for recipe image reprocessing (#6822) 2026-01-02 13:17:07 -06:00
Arsène Reymond
1b57310535 fix: allow start attribute on ordered lists (SafeMarkdown) (#6820)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2026-01-02 19:02:11 +00:00
Patrick Lehner (he/him)
2b15d9a515 fix: Make quantity input in shopping list item editor visually consistent with other inputs (#6810) 2026-01-02 12:51:53 -06:00
Hayden
adc9c0b970 chore(l10n): New Crowdin updates (#6804) 2025-12-31 00:36:01 +00:00
renovate[bot]
bec1708891 chore(deps): update node.js to b52a8d1 (#6800)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-30 10:33:30 -06:00
Patrick Lehner (he/him)
66bb545454 dev: Small .gitignore fixes (#6796) 2025-12-30 15:42:38 +00:00
renovate[bot]
c1ebf04291 chore(deps): update node.js to 33587cf (#6795)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-30 05:20:34 +00:00
13 changed files with 56 additions and 58 deletions

5
.gitignore vendored
View File

@@ -70,8 +70,11 @@ wheels/
.installed.cfg
*.egg
# packaged output - temporarily written here by `uv build`
/mealie-*
# frontend copied into Python module for packaging purposes
/mealie/frontend/
/mealie/frontend
# PyInstaller
# Usually these files are written by a python script from a template

View File

@@ -1,7 +1,7 @@
###############################################
# Frontend Build
###############################################
FROM node:24@sha256:20988bcdc6dc76690023eb2505dd273bdeefddcd0bde4bfd1efe4ebf8707f747 \
FROM node:24@sha256:b52a8d1206132b36d60e51e413d9a81336e8a0206d3b648cabd6d5a49c4c0f54 \
AS frontend-builder
WORKDIR /frontend

View File

@@ -31,7 +31,7 @@ To deploy mealie on your local network, it is highly recommended to use Docker t
We've gone through a few versions of Mealie v1 deployment targets. We have settled on a single container deployment, and we've begun publishing the nightly container on github containers. If you're looking to move from the old nightly (split containers _or_ the omni image) to the new nightly, there are a few things you need to do:
1. Take a backup just in case!
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v3.9.1`
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v3.9.2`
3. Take the external port from the frontend container and set that as the port mapped to port `9000` on the new container. The frontend is now served on port 9000 from the new container, so it will need to be mapped for you to have access.
4. Restart the container

View File

@@ -10,7 +10,7 @@ PostgreSQL might be considered if you need to support many concurrent users. In
```yaml
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v3.9.1 # (3)
image: ghcr.io/mealie-recipes/mealie:v3.9.2 # (3)
container_name: mealie
restart: always
ports:

View File

@@ -11,7 +11,7 @@ SQLite is a popular, open source, self-contained, zero-configuration database th
```yaml
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v3.9.1 # (3)
image: ghcr.io/mealie-recipes/mealie:v3.9.2 # (3)
container_name: mealie
restart: always
ports:

View File

@@ -10,11 +10,8 @@
:label="$t('form.quantity-label-abbreviated')"
:min="0"
:precision="null"
variant="plain"
control-variant="stacked"
inset
density="compact"
class="centered-number-input"
style="width: 100px;"
/>
</div>
@@ -242,10 +239,3 @@ export default defineNuxtComponent({
},
});
</script>
<style scoped>
.centered-number-input :deep(.v-field) {
display: flex;
align-items: center;
}
</style>

View File

@@ -31,7 +31,7 @@ export default defineNuxtComponent({
],
ALLOWED_ATTR: [
"href", "src", "alt", "height", "width", "class", "allow", "title", "allowfullscreen", "frameborder",
"scrolling", "cite", "datetime", "name", "abbr", "target", "border",
"scrolling", "cite", "datetime", "name", "abbr", "target", "border", "start",
],
});

View File

@@ -342,9 +342,9 @@
"breakfast": "Café da manhã",
"lunch": "Almoço",
"dinner": "Jantar",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"snack": "Lanche",
"drink": "Bebida",
"dessert": "Sobremesa",
"type-any": "Qualquer",
"day-any": "Qualquer",
"editor": "Editor",
@@ -445,7 +445,7 @@
"upload-a-recipe": "Enviar uma Receita",
"upload-individual-zip-file": "Enviar um arquivo .zip individual exportado a partir de outra instância do Mealie.",
"url-form-hint": "Copie e cole um link do seu site de receita favorito",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"copy-and-paste-the-source-url-of-your-data-optional": "Copie e cole o URL de origem dos seus dados (opcional)",
"view-scraped-data": "Visualizar Dados Rastreados",
"trim-whitespace-description": "Aparar o espaço em branco e à direita, bem como linhas em branco",
"trim-prefix-description": "Aparar primeiro caractere de cada linha",
@@ -637,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Tente o importador em massa",
"scrape-recipe-have-raw-html-or-json-data": "Tem dados HTML ou JSON brutos?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Você pode importar diretamente de dados brutos",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Site sendo bloqueado?",
"scrape-recipe-try-importing-raw-html-instead": "Tente importar o HTML ao invés disso.",
"import-original-keywords-as-tags": "Importar palavras-chave originais como marcadores",
"stay-in-edit-mode": "Permanecer no modo de edição",
"parse-recipe-ingredients-after-import": "Interpretar os ingredientes da receita após importar",
@@ -1430,11 +1430,11 @@
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"required": "Este campo é obrigatório",
"invalid-email": "O e-mail deve ser válido",
"invalid-url": "Precisa ser uma URL válida",
"no-whitespace": "Nenhum espaço em branco é permitido",
"min-length": "Precisa ter pelo menos {min} caracteres",
"max-length": "Pode ter até {max} caracteres"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "mealie",
"version": "3.9.1",
"version": "3.9.2",
"private": true,
"scripts": {
"dev": "nuxt dev",

View File

@@ -5043,14 +5043,14 @@
"hake": {
"aliases": [],
"description": "",
"name": "hake",
"plural_name": "hakes"
"name": "merlu",
"plural_name": "merlus"
},
"pollock": {
"aliases": [],
"description": "",
"name": "pollock",
"plural_name": "pollocks"
"name": "lieu noir",
"plural_name": "lieu noir"
},
"salt cod": {
"aliases": [],
@@ -5217,8 +5217,8 @@
"pike": {
"aliases": [],
"description": "",
"name": "pike",
"plural_name": "pikes"
"name": "brochet",
"plural_name": "brochets"
},
"pickled herring": {
"aliases": [],
@@ -5469,8 +5469,8 @@
"tiny fish": {
"aliases": [],
"description": "",
"name": "tiny fish",
"plural_name": "tiny fish"
"name": "petit poisson",
"plural_name": "petits poissons"
},
"tuna belly": {
"aliases": [],
@@ -5569,8 +5569,8 @@
"crawfish": {
"aliases": [],
"description": "",
"name": "crawfish",
"plural_name": "crawfish"
"name": "écrevisse",
"plural_name": "écrevisses"
},
"octopu": {
"aliases": [],
@@ -5635,8 +5635,8 @@
"squid ink": {
"aliases": [],
"description": "",
"name": "squid ink",
"plural_name": "squid inks"
"name": "encre de seiche",
"plural_name": "encres de seiches"
},
"dried prawn": {
"aliases": [],
@@ -5719,8 +5719,8 @@
"sea urchin": {
"aliases": [],
"description": "",
"name": "sea urchin",
"plural_name": "sea urchins"
"name": "oursin",
"plural_name": "oursins"
},
"abalone": {
"aliases": [],
@@ -5743,8 +5743,8 @@
"smoked mussel": {
"aliases": [],
"description": "",
"name": "smoked mussel",
"plural_name": "smoked mussels"
"name": "moule fumée",
"plural_name": "moules fumées"
},
"sea snail": {
"aliases": [],
@@ -5761,8 +5761,8 @@
"prepared crab cake": {
"aliases": [],
"description": "",
"name": "prepared crab cake",
"plural_name": "prepared crab cakes"
"name": "gâteau de crabe",
"plural_name": "gâteaux de crabe"
},
"sea lettuce": {
"aliases": [],
@@ -6095,8 +6095,8 @@
"chipotle": {
"aliases": [],
"description": "",
"name": "chipotle",
"plural_name": "chipotles"
"name": "piment chipotle",
"plural_name": "piments chipotles"
},
"fenugreek": {
"aliases": [],
@@ -6107,8 +6107,8 @@
"onion flake": {
"aliases": [],
"description": "",
"name": "onion flake",
"plural_name": "onion flakes"
"name": "oignon émincé",
"plural_name": "oignons émincés"
},
"matcha powder": {
"aliases": [],
@@ -6263,8 +6263,8 @@
"garlic flake": {
"aliases": [],
"description": "",
"name": "garlic flake",
"plural_name": "garlic flakes"
"name": "ail émincé",
"plural_name": "aulx émincés"
},
"dried cilantro": {
"aliases": [],
@@ -15705,7 +15705,7 @@
"almond extract": {
"aliases": [],
"description": "",
"name": "extrait d'amandes",
"name": "extrait d'amande",
"plural_name": "extraits d'amandes"
},
"food coloring": {

View File

@@ -4,7 +4,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
import sqlalchemy as sa
from PIL import Image
from PIL import Image, UnidentifiedImageError
from pydantic import UUID4
from mealie.core import root_logger
@@ -84,7 +84,12 @@ def reprocess_recipe_images(recipe_id: UUID4, force_all: bool = False) -> None:
image_file = service.dir_image / image_filename
image_file.unlink(missing_ok=True)
service.minifier.minify(original_image, force=True)
try:
service.minifier.minify(original_image, force=True)
except UnidentifiedImageError:
pass # source image is corrupted or invalid; skip
except Exception:
logger.exception(f"Failed to reprocess images for recipe {recipe_id}")
# Reprocess timeline event images
timeline_dir = service.dir_image_timeline

View File

@@ -1,6 +1,6 @@
[project]
name = "mealie"
version = "3.9.1"
version = "3.9.2"
description = "A Recipe Manager"
authors = [{ name = "Hayden", email = "hay-kot@pm.me" }]
license = "AGPL-3.0-only"

2
uv.lock generated
View File

@@ -811,7 +811,7 @@ wheels = [
[[package]]
name = "mealie"
version = "3.9.1"
version = "3.9.2"
source = { editable = "." }
dependencies = [
{ name = "aiofiles" },