switch to ical.js and cleanup obsolete files - v0.4.6 [skip-ci]
All checks were successful
Build SilverBullet Plug / build (push) Successful in 11s

This commit is contained in:
2026-02-21 16:05:54 -08:00
parent 30731c7752
commit 139ab71db7
26 changed files with 174 additions and 454 deletions

View File

@@ -1,9 +1,9 @@
import { clientStore, config, datastore, editor, index } from "@silverbulletmd/silverbullet/syscalls";
import { convertIcsCalendar } from "https://esm.sh/ts-ics@2.4.0";
import ICAL from "ical.js";
import { RRule, RRuleSet } from "rrule";
import { getUtcOffsetMs, resolveIanaName } from "./timezones.ts";
const VERSION = "0.4.4";
const VERSION = "0.4.6";
const CACHE_KEY = "icalendar:lastSync";
console.log(`[iCalendar] Plug script executing at top level (Version ${VERSION})`);
@@ -321,27 +321,37 @@ async function fetchAndParseCalendar(source: any, windowDays = 365, displayTimez
return [];
}
const text = await response.text();
const calendar = convertIcsCalendar(undefined, text);
if (!calendar || !calendar.events) {
return [];
}
const events: any[] = [];
for (const icsEvent of calendar.events) {
if (icsEvent.status?.toUpperCase() === "CANCELLED") continue;
const jcalData = ICAL.parse(text);
const vcalendar = new ICAL.Component(jcalData);
const vevents = vcalendar.getAllSubcomponents("vevent");
// Resolve start time (returns UTC Date)
const startDateUTC = await resolveEventStart(icsEvent);
if (!startDateUTC) continue;
const events: any[] = [];
for (const vevent of vevents) {
const icsEvent = new ICAL.Event(vevent);
const status = vevent.getFirstPropertyValue("status") as string | null;
// Resolve end time (returns UTC Date)
const endDateUTC = await resolveEventEnd(icsEvent);
if (status?.toUpperCase() === "CANCELLED") continue;
// Extract raw properties for recurrence expansion
const summary = icsEvent.summary;
const uid = icsEvent.uid;
const description = icsEvent.description;
const location = icsEvent.location;
const rrule = vevent.getFirstPropertyValue("rrule");
const exdates = vevent.getAllProperties("exdate").map((p: any) => p.getFirstValue().toJSDate().toISOString());
// Resolve start/end times
const startDateUTC = icsEvent.startDate.toJSDate();
const endDateUTC = icsEvent.endDate ? icsEvent.endDate.toJSDate() : null;
const rawTz = icsEvent.start?.local?.timezone || (icsEvent.start as any)?.timezone || "UTC";
const rawTz = icsEvent.startDate.timezone || "UTC";
const baseEvent = {
...icsEvent,
name: icsEvent.summary || "Untitled Event",
uid,
summary,
name: summary || "Untitled Event",
description,
location,
// Store both UTC (for sorting/comparison) and local (for display)
start: startDateUTC.toISOString(),
startLocal: dateToTimezoneString(startDateUTC, displayTimezone),
@@ -349,7 +359,9 @@ async function fetchAndParseCalendar(source: any, windowDays = 365, displayTimez
endLocal: endDateUTC ? dateToTimezoneString(endDateUTC, displayTimezone) : undefined,
tag: "ical-event",
sourceName: source.name,
timezone: rawTz
timezone: rawTz,
rrule: rrule ? rrule.toString() : undefined,
exdate: exdates.length > 0 ? exdates : undefined
};
if (rawTz !== "UTC" && rawTz !== "None" && !resolveIanaName(rawTz)) {