Architecture#
Source layout#
All of the plugin’s logic lives under src/:
File |
Responsibility |
|---|---|
|
Plugin entry point: loads settings, registers the sidebar/month views, the editor suggest, the live preview extension, and the post-processor; adds the Open calendar in sidebar, Open calendar in a new tab, and Refresh calendars commands. |
|
Shared types: |
|
Default settings and the settings UI. |
|
Looks up the current Obsidian UI language via the official
|
|
A minimal read-only CalDAV client: calendar discovery
( |
|
An iCalendar (RFC 5545) parser extracting |
|
Expands a |
|
Resolves an account’s configured time zone (an IANA zone name via
|
|
|
|
Triggers on |
|
Reads a note’s |
|
Scans the vault for |
|
Builds the |
|
The inline event chip, and the click-to-open detail popup (a
manually positioned floating panel, closed on outside click or
Esc). The lookup is scoped to the |
|
A CodeMirror 6 |
|
A Markdown post-processor that does the same replacement for Reading
view, by scanning rendered text nodes directly - |
|
The sidebar agenda list: a fixed 30-day window of |
|
The full-tab month grid view (same |
|
The year/month picker opened from the month view’s heading, with a click-to-edit year field. |
Data flow#
settingsTab.ts --> CalDavAccount[] (server URL, credentials, calendars)
|
v
caldav/client.ts --> PROPFIND/REPORT over requestUrl
| (discovery + event fetch)
v
caldav/ics.ts --> parses each VEVENT into a CalDavEvent
|
v
caldav/recurrence.ts --> expands RRULE occurrences on demand
|
v
caldav/store.ts --> merged, cached, scoped CalDavEvent[]
|
+--> editorSuggest/*.ts --> autocomplete while typing
|
+--> render/livePreview.ts --> widget/chip (Live Preview)
|
+--> render/postProcessor.ts --> widget/chip (Reading view)
| |
| v
| render/eventChip.ts + eventCard.ts --> click-to-open detail popup
|
+--> view/AgendaItemView.ts / vue/AgendaView.vue --> sidebar list
|
+--> view/MonthItemView.ts / vue/MonthView.vue --> month grid
notes/noteEvents.ts (vault-wide frontmatter scan) --> NoteEvent[]
|
+--> (merged into a CalendarListItem[] alongside CalDavEvent[],
inside AgendaItemView.ts/MonthItemView.ts, right before
the sidebar list / month grid above render - nothing else
in this diagram ever sees a NoteEvent)
Reference syntax#
{{hrcal:<accountName>:<calendarName>:date:YYYY-MM-DD}} renders as a date
widget; {{hrcal:<accountName>:<calendarName>:event:<uid>}} renders as an
event chip. Both are normally inserted by the staged {{hrcal: editor
suggest, but either can be typed by hand too — an unresolvable reference
renders as a faded, dashed chip (or, for a date whose account/calendar
doesn’t match a registered one, a warning inside the widget) instead of
failing silently.
Both kinds are always scoped by the accountName/calendarName named
directly in the reference - note frontmatter (harang-account/
harang-calendar, see Usage) plays no role here any more.
Note events (harang-date/harang-repeat/harang-time)#
Unrelated to the reference syntax above: a note carrying harang-date
frontmatter (see Usage) becomes a NoteEvent and shows up as an
item in the sidebar agenda list and month grid only - never in a
{{hrcal:...}} date widget or as an event chip, and never written to or
read from a CalDAV server. harang-repeat reuses the same rrule
package as caldav/recurrence.ts, but with its own from-scratch
expansion logic (see notes/noteEvents.ts above) rather than sharing
that module’s function directly, since a note event has no time-of-day at
all by default and needs consistently UTC-midnight-anchored date math
throughout to avoid the local/UTC all-day mismatch this project has hit
(and fixed) several times elsewhere. harang-time layers an optional
HH:MM-HH:MM display range on top of that all-day date math - it only
affects how a NoteEvent is labeled and sorted alongside timed CalDAV
events, not the (still UTC-midnight-anchored) date expansion itself.
No runtime dependencies beyond rrule#
Beyond what Obsidian itself provides (the obsidian package, CodeMirror
6, Vue 3) and the rrule package for
recurrence expansion, the plugin has no runtime dependencies — the CalDAV
client and iCalendar parser are both hand-written rather than pulled in
from npm, keeping the bundle small and avoiding exposure to a third-party
HTTP/XML parsing library’s own vulnerabilities.