From 9f321851f8c159208bfd8fe4eac67f6d8a6b6389 Mon Sep 17 00:00:00 2001 From: Ulas Kalayci Date: Tue, 21 Apr 2026 17:23:30 +0200 Subject: [PATCH] chore: release v0.22.2 Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- public/locales/de.json | 2 +- server/services/ics-parser.js | 4 ++++ 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 476a64d..60bf919 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.22.2] - 2026-04-21 + +### Fixed +- Locale file (`de.json`) no longer causes a JSON parse error that made the app completely unusable. The `recipes.deleteConfirm` value contained a bare ASCII double-quote inside a JSON string, which prematurely terminated the string and broke every page load. +- ICS calendar subscriptions now respect the `COUNT` parameter in RRULE (RFC 5545). Previously, events with a limited number of occurrences (e.g. `RRULE:FREQ=WEEKLY;COUNT=3`) were incorrectly shown as upcoming because the expansion loop iterated to the sync window end regardless of the occurrence limit. + ## [0.22.1] - 2026-04-21 ### Fixed diff --git a/package-lock.json b/package-lock.json index 8654442..1e216c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.22.1", + "version": "0.22.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.22.1", + "version": "0.22.2", "license": "MIT", "dependencies": { "bcrypt": "^6.0.0", diff --git a/package.json b/package.json index ee1f824..ca0966d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.22.1", + "version": "0.22.2", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module", diff --git a/public/locales/de.json b/public/locales/de.json index 69aa1dc..f230431 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -697,7 +697,7 @@ "ingredientsLabel": "Zutaten", "addToMeals": "In Essensplan übernehmen", "openLink": "Rezept-Link öffnen", - "deleteConfirm": "Rezept „{{title}}" löschen?", + "deleteConfirm": "Rezept \"{{title}}\" löschen?", "created": "Rezept gespeichert.", "updated": "Rezept aktualisiert.", "deleted": "Rezept gelöscht.", diff --git a/server/services/ics-parser.js b/server/services/ics-parser.js index 000cdc5..0d64924 100644 --- a/server/services/ics-parser.js +++ b/server/services/ics-parser.js @@ -117,10 +117,14 @@ function expandRRULE(vevent, windowStart, windowEnd) { const e = new Date(vevent.allDay ? vevent.dtend + 'T00:00:00Z' : vevent.dtend); if (!isNaN(s) && !isNaN(e)) durationMs = e - s; } + const countMatch = /;COUNT=(\d+)/i.exec(vevent.rrule); + const maxCount = countMatch ? parseInt(countMatch[1], 10) : null; let current = startDate, iterations = 0; const MAX_ITER = 1500; while (current <= windowEnd && iterations < MAX_ITER) { iterations++; + if (maxCount !== null && iterations > maxCount) break; + if (current >= windowStart) { const occStart = current + timeSuffix; let occEnd = null;