forked from GitHubMirrors/silverbullet-icalendar
Compare commits
14 Commits
523b49dd3a
...
c9a703975d
| Author | SHA1 | Date | |
|---|---|---|---|
| c9a703975d | |||
| 842586c129 | |||
| c6532e5aca | |||
| 42fb8be61c | |||
| f8a6fbafda | |||
| dbc7ef29aa | |||
| 7edc0997b2 | |||
| c3fd3aee20 | |||
| e5b063269f | |||
| 31ca364a7c | |||
| e7c69aa3f7 | |||
| 255988e6f3 | |||
| ada9f6694c | |||
| cd0fdf5f98 |
2
PLUG.md
2
PLUG.md
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Library/sstent/icalendar
|
||||
version: "0.3.31"
|
||||
version: "0.3.32"
|
||||
tags: meta/library
|
||||
files:
|
||||
- icalendar.plug.js
|
||||
|
||||
@@ -16,3 +16,8 @@ This file tracks all major tracks for the project. Each track has its own detail
|
||||
|
||||
- [x] **Track: Fix RRULE object expansion error by correctly mapping object keys to standard iCalendar RRULE properties.**
|
||||
*Link: [./tracks/fix_rrule_object_mapping_20260219/](./tracks/fix_rrule_object_mapping_20260219/)*
|
||||
|
||||
---
|
||||
|
||||
- [x] **Track: Fix RRULE UNTIL object conversion error: Invalid UNTIL value: [object Object]**
|
||||
*Link: [./tracks/fix_rrule_until_conversion_20260219/](./tracks/fix_rrule_until_conversion_20260219/)*
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Track fix_rrule_until_conversion_20260219 Context
|
||||
|
||||
- [Specification](./spec.md)
|
||||
- [Implementation Plan](./plan.md)
|
||||
- [Metadata](./metadata.json)
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"track_id": "fix_rrule_until_conversion_20260219",
|
||||
"type": "bug",
|
||||
"status": "new",
|
||||
"created_at": "2026-02-19T00:00:00Z",
|
||||
"updated_at": "2026-02-19T00:00:00Z",
|
||||
"description": "Fix RRULE UNTIL object conversion error: Invalid UNTIL value: [object Object]"
|
||||
}
|
||||
19
conductor/tracks/fix_rrule_until_conversion_20260219/plan.md
Normal file
19
conductor/tracks/fix_rrule_until_conversion_20260219/plan.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Implementation Plan - Fix RRULE UNTIL Conversion
|
||||
|
||||
## Phase 1: Reproduction [checkpoint: 02fcb7e]
|
||||
- [x] Task: Reproduce `Invalid UNTIL value` error 17de604
|
||||
- [x] Add a test case in `icalendar_test.ts` where `rrule` object has an `until` property as a `Date`.
|
||||
- [x] Run the test and confirm it fails with `Error: Invalid UNTIL value: [object Object]`.
|
||||
- [x] Task: Conductor - User Manual Verification 'Reproduction' (Protocol in workflow.md)
|
||||
|
||||
## Phase 2: Fix Implementation [checkpoint: 0f334b2]
|
||||
- [x] Task: Implement value formatting logic in `icalendar.ts` 331d0ab
|
||||
- [x] Update `expandRecurrences` to use a helper for property value conversion.
|
||||
- [x] Ensure `Date` objects are formatted as `YYYYMMDDTHHMMSSZ`.
|
||||
- [x] Run the test to confirm it passes.
|
||||
- [x] Task: Conductor - User Manual Verification 'Fix Implementation' (Protocol in workflow.md)
|
||||
|
||||
## Phase 3: Verification & Cleanup [checkpoint: a02f228]
|
||||
- [x] Task: Full Regression Check d090334
|
||||
- [x] Run all tests in `icalendar_test.ts`.
|
||||
- [x] Task: Conductor - User Manual Verification 'Verification & Cleanup' (Protocol in workflow.md)
|
||||
20
conductor/tracks/fix_rrule_until_conversion_20260219/spec.md
Normal file
20
conductor/tracks/fix_rrule_until_conversion_20260219/spec.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Specification: Fix RRULE UNTIL Object Conversion
|
||||
|
||||
## Overview
|
||||
The conversion of RRULE objects to strings fails for nested objects like `UNTIL` dates, resulting in `UNTIL=[object Object]`. This causes the `rrule` library to fail during expansion.
|
||||
|
||||
## Functional Requirements
|
||||
- **Robust Value Formatting:** Implement `formatRRuleValue` to handle various types of RRULE values:
|
||||
- **Date Objects:** Convert to `YYYYMMDDTHHMMSSZ`.
|
||||
- **Nested Date Objects:** (e.g., `{ date: Date }` from `ts-ics`) Extract and convert.
|
||||
- **Other Types:** Default to string conversion.
|
||||
- **Mapping Preservation:** Maintain the existing `RRULE_KEY_MAP` for key translation.
|
||||
|
||||
## Implementation Steps
|
||||
1. **Reproduce:** Add test `expandRecurrences - object rrule with until` in `icalendar_test.ts` using a Date object for `until`. Verify it fails with `Invalid UNTIL value`.
|
||||
2. **Fix:** Update `expandRecurrences` in `icalendar.ts` to use a formatting helper for values.
|
||||
3. **Verify:** Confirm the test case passes.
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Test `expandRecurrences - object rrule with until` passes.
|
||||
- [ ] The generated string correctly represents the date (e.g., `UNTIL=20260219T000000Z`).
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "icalendar-plug",
|
||||
"version": "0.3.31",
|
||||
"version": "0.3.32",
|
||||
"nodeModulesDir": "auto",
|
||||
"tasks": {
|
||||
"sync-version": "deno run -A scripts/sync-version.ts",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: icalendar
|
||||
version: 0.3.31
|
||||
version: 0.3.32
|
||||
author: sstent
|
||||
index: icalendar.ts
|
||||
# Legacy SilverBullet permission name
|
||||
|
||||
18
icalendar.ts
18
icalendar.ts
@@ -3,7 +3,7 @@ import { convertIcsCalendar } from "https://esm.sh/ts-ics@2.4.0";
|
||||
import { RRule, RRuleSet } from "rrule";
|
||||
import { getUtcOffsetMs, resolveIanaName } from "./timezones.ts";
|
||||
|
||||
const VERSION = "0.3.31";
|
||||
const VERSION = "0.3.32";
|
||||
const CACHE_KEY = "icalendar:lastSync";
|
||||
|
||||
console.log(`[iCalendar] Plug script executing at top level (Version ${VERSION})`);
|
||||
@@ -29,6 +29,20 @@ const RRULE_KEY_MAP: Record<string, string> = {
|
||||
"freq": "FREQ", // Just in case
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats an RRULE value for the string representation.
|
||||
* Specifically handles Date objects and nested date objects from ts-ics.
|
||||
*/
|
||||
function formatRRuleValue(v: any): string {
|
||||
if (v instanceof Date) {
|
||||
return v.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z";
|
||||
}
|
||||
if (typeof v === "object" && v !== null && v.date instanceof Date) {
|
||||
return v.date.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z";
|
||||
}
|
||||
return String(v);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
@@ -186,7 +200,7 @@ export function expandRecurrences(icsEvent: any, windowDays = 365): any[] {
|
||||
cleanRule = Object.entries(rruleStr)
|
||||
.map(([k, v]) => {
|
||||
const standardKey = RRULE_KEY_MAP[k.toLowerCase()] || k.toUpperCase();
|
||||
return `${standardKey}=${v}`;
|
||||
return `${standardKey}=${formatRRuleValue(v)}`;
|
||||
})
|
||||
.join(";");
|
||||
} else {
|
||||
|
||||
@@ -206,3 +206,22 @@ Deno.test("expandRecurrences - object rrule (Reproduction of missing events)", (
|
||||
assert(!warningLogged, "Should NOT have logged a warning for object rrule");
|
||||
});
|
||||
|
||||
|
||||
Deno.test("expandRecurrences - object rrule with until", () => {
|
||||
const now = new Date();
|
||||
const start = new Date(now.getTime() - 10 * 86400000);
|
||||
const startStr = localDateString(start);
|
||||
const untilDate = new Date(now.getTime() + 10 * 86400000);
|
||||
|
||||
const icsEvent = {
|
||||
summary: "Object RRULE UNTIL Event",
|
||||
start: startStr,
|
||||
rrule: { frequency: "DAILY", until: { date: untilDate } }
|
||||
};
|
||||
|
||||
const results = expandRecurrences(icsEvent, 30);
|
||||
// Should now return multiple occurrences
|
||||
assert(results.length > 1, `Expected > 1 occurrences, got ${results.length}`);
|
||||
assertEquals(results[0].recurrent, true);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user