joplin-plugin-my-calendar 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,50 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [1.8.0](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/compare/v1.7.2...v1.8.0) (2026-07-24)
6
+
7
+
8
+ ### ✨ Features
9
+
10
+ * add in-panel event creation form ([651a4f6](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/651a4f6fd9ae7556e555a4e1d0621b5ca53e5c9d))
11
+ * add manual scheduled ICS import button ([f3afefb](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/f3afefb9e1daab8e1c935780a59fcdb9869b30dc))
12
+ * dim completed todo events and show checked icon ([a57dd03](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/a57dd03f4c3bd0d5d1499f05193465a350afc0cc))
13
+ * improve add event validation and UX ([b762bff](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/b762bff96ceef7646c43f15a53b0b56eb2c8cfde))
14
+ * individual colors for lighg and dark modes ([e49075d](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/e49075d0b81abc0673d729ac5543612681381943))
15
+
16
+
17
+ ### 🐛 Bug Fixes
18
+
19
+ * apply cancelled recurrence exceptions to existing masters ([cf6626e](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/cf6626ef7637ec42a2c0527d693a208afaa2f9b4))
20
+ * automate Joplin restart and DevTools opening ([3a3601c](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/3a3601c7b8e632843168a70b3a20b02a9f15d4a6))
21
+ * automate Joplin restart and DevTools opening 2 ([3fa92ab](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/3fa92ab06a23290ee2e1d42ba5b23983a2672195))
22
+ * bound and index alarm reconciliation ([2c55e3f](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/2c55e3fa1b7b6d46a729ab38cfba79858453e70a))
23
+ * cap recurrence expansion for large ranges ([aee0424](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/aee0424bfce8639fc1acf44dd3c9da53af32b7ce))
24
+ * clear range cache after calendar data changes ([e7093bb](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/e7093bb4c912c50dc8af1bbd8719bd82a13bfe0f))
25
+ * commit ICS import state only after successful writes ([de9246c](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/de9246cc14d1d036259bd9b709457a903f3a668a))
26
+ * dedupe imported events across notebooks ([f8ce782](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/f8ce782b0d098bd1cb6b1b9ec46a496e7d89f41a))
27
+ * dedupe imported events across notebooks ([813a0a9](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/813a0a9c0c2fa1528bb731fe48343fbcadb0d70a))
28
+ * deduplicate event keys before concurrent import ([8fce9be](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/8fce9be373a7a3f45fd721f993b1dcc9810291e1))
29
+ * delete imported alarms when ICS alarms are disabled ([28e5c71](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/28e5c717ec163b58ae40b268e580284d4cd7cf11))
30
+ * finalize scheduled import cache invalidation ([9532e0d](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/9532e0d51d0889c24a68520c2b06b25fdb26cfbb))
31
+ * make release workflow resumable and authentication-aware ([c0169d0](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/c0169d0d9f237ab52e52b5a62a46881dbd450aa6))
32
+ * normalize all-day event semantics ([80fb46c](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/80fb46c1bf143f37777c2624b3c08fe1755fdcdb))
33
+ * preserve alarm creation after normalization failure ([0751f63](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/0751f630980d6fa98f9d599721a66254fa9f69e7))
34
+ * preserve ICS metadata after note parsing ([4a5c18e](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/4a5c18e3e5e6c694bb03b144dd35393b7c3fc5a9))
35
+ * prevent alarm cleanup from emptying Joplin trash ([b4a18ee](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/b4a18ee69d98f071209fe57adc47e117997307d8))
36
+ * prevent stale note refresh from overwriting cache ([8f8a701](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/8f8a7015a98838ab365f13c0ce24d43dc4da59eb))
37
+ * refine ICS import form styling and file picker ([277bcfd](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/277bcfd45f817b702d13ff7a0854b9a16df85d8c))
38
+ * reject normalized invalid calendar dates ([b602c49](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/b602c492f09d1bbd3bf419eed153a9b503407dfe))
39
+ * reject unsupported ICS timezone identifiers ([6681795](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/6681795afe439c0ef8a27af2b1d8a9098d26aa1d))
40
+ * report tag attachment failures as partial success ([10246f6](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/10246f64021431671663a5f6a1d27d4c216298c5))
41
+ * skip recurrence instances in DST gaps ([384020f](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/384020f07b85fd7080c870a0651f0dcc805821e5))
42
+ * stabilize events cache invalidation ([87777e9](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/87777e9f019ee7c9dee00344e7d5d88ee207b19f))
43
+ * surface duplicate event ownership warnings ([5e061b8](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/5e061b84b78cc9067641f1b8238db1421018135a))
44
+ * unify event form control padding ([3f96326](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/3f96326761c6e603e94a64af44e63886317cce83))
45
+ * unify event form control padding 2 ([0bf97ea](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/0bf97ea01edd6d5d9d68a6aff74bc744bbf5f535))
46
+ * unify event form control padding 3 ([212f08f](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/212f08f0079cba87d05e9f6775aeae8a57182f2f))
47
+ * use half-open boundaries for calendar ranges ([ebbaf3b](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/commit/ebbaf3b633f9806e9a08bec54045ba58a38c1ce3))
48
+
5
49
  ### [1.7.2](https://github.com/volodymyroliinyk/joplin-plugin-my-calendar/compare/v1.7.1...v1.7.2) (2026-06-13)
6
50
 
7
51
 
package/README.md CHANGED
@@ -5,73 +5,76 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![Support via PayPal](https://img.shields.io/badge/Support-PayPal-00457C?style=flat-square&logo=paypal)](https://www.paypal.me/volodymyroliinykca)
7
7
 
8
- **My Calendar** is a powerful, flexible, and privacy-focused calendar plugin for [Joplin](https://joplinapp.org/). It
9
- turns your notes into calendar events, providing a unified view of your schedule directly within your favorite
10
- note-taking app.
8
+ My Calendar adds a calendar panel to Joplin. Events are stored as regular Joplin notes, so they stay with your notes and
9
+ use your normal Joplin sync.
11
10
 
12
- | Light Mode | Dark Mode |
11
+ | Light mode | Dark mode |
13
12
  |:--------------------------------------------------:|:------------------------------------------------:|
14
13
  | ![Light View](./assets/screenshots/light_view.png) | ![Dark View](./assets/screenshots/dark_view.png) |
15
14
 
16
- ---
17
-
18
- ## 🌟 Key Features
19
-
20
- - **Integrated Monthly Calendar**:
21
- - **Visual Grid**: View your schedule with event bars and alarm indicators.
22
- - **Navigation**: Quick jump to any date via the month/year picker.
23
- - **Quick Recovery**: Use `⟳` in the toolbar to clear cached events and instantly refresh the month.
24
- - **Customization**: Toggle week numbers and choose Monday or Sunday start.
25
- - **Smart Day View**:
26
- - **Detailed Timeline**: See a chronological list of the day's events with a current time indicator.
27
- - **Grouped Mode**: Optional grouping into **Ongoing / Feature / Past** with dynamic reclassification.
28
- - **Interactive**: Click events to open the corresponding note.
29
- - **Notes as Events**:
30
- - **Simple Syntax**: Turn any note into an event by adding a metadata block.
31
- - **Rich Details**: Support for timezones, locations, custom colors, and recurrence.
32
- - **Robust ICS Import**:
33
- - **Broad Compatibility**: Import `.ics` files from Google Calendar, Outlook, Apple, etc.
34
- - **Recurrence**: Full support for complex recurring event patterns.
35
- - **Smart Sync**: Deduplicates events and preserves local changes like custom colors.
36
- - **Native Alarms**:
37
- - **System Notifications**: Automatically converts calendar alarms into Joplin "Todo" notes, triggering native
38
- reminders on Desktop and Mobile.
39
- - **Security & Privacy**:
40
- - **Sanitized**: Protection against malicious Markdown/CSS.
41
- - **Local**: Works with Joplin's existing sync; no external servers required.
42
-
43
- ### 📱 Platform Availability
44
-
45
- While we strive for parity, some features are specific to the Desktop version due to platform-specific APIs.
46
-
47
- | Feature | Desktop | Mobile |
48
- |:-----------------------------------|:-------:|:------:|
49
- | Monthly Calendar Grid | ✅ | ✅ |
50
- | Smart Day View | ✅ | ✅ |
51
- | Native Joplin Settings | ✅ | ✅ |
52
- | ICS File Import | ✅ | ❌ |
53
- | Scheduled ICS Import from URLs | ✅ | ❌ |
54
- | Quick ICS Export Links | ✅ | ❌ |
55
- | Markdown Sanitization | ✅ | ✅ |
56
- | Automatic Alarms (Todo generation) | ✅ | ✅* |
57
-
58
- *\*Note: Alarms are generated/synced during the import process on Desktop. Once created as "Todo" notes, they will sync
59
- and trigger notifications on Mobile automatically.*
60
-
61
- ---
62
-
63
- ## 🚀 Getting Started
64
-
65
- ### 1. Installation
66
-
67
- 1. Open **Joplin Desktop**.
68
- 2. Go to `Tools` > `Options` (Windows/Linux) or `Joplin` > `Settings` (macOS).
69
- 3. Select `Plugins` and search for `My Calendar`.
70
- 4. Click **Install** and restart Joplin.
71
-
72
- ### 2. Manual Event Creation
73
-
74
- You don't need to import files to use the calendar. Simply add the following block to any note:
15
+ ## Features
16
+
17
+ - Month calendar with colored events, alarm markers, quick month and year selection, week numbers, and Monday or Sunday
18
+ as the first day of the week.
19
+ - Day list with current, future, and past events. Completed Joplin Todo events are dimmed and marked with a check.
20
+ - Event timeline and 12-hour or 24-hour time display.
21
+ - Click an event to open its Joplin note.
22
+ - Create events from a form in the calendar panel, with field checks and searchable Joplin tags.
23
+ - Create events by adding a `mycalendar-event` block to any note.
24
+ - Store more than one event in the same note.
25
+ - Daily, weekly, monthly, and yearly repeats.
26
+ - All-day events, timezones, locations, descriptions, colors, and excluded repeat dates.
27
+ - Manual ICS file import on desktop.
28
+ - Scheduled ICS import from HTTPS links on desktop.
29
+ - Optional Joplin Todo reminders from ICS alarms.
30
+ - Toolbar buttons to clear the event cache and run scheduled imports now.
31
+ - Light and dark theme support.
32
+ - Desktop and mobile support for the calendar and event form.
33
+
34
+ ### Platform support
35
+
36
+ | Feature | Desktop | Mobile |
37
+ |:--------------------------------------|:-------:|:------:|
38
+ | Calendar and day list | ✅ | ✅ |
39
+ | Create events | ✅ | ✅ |
40
+ | Plugin settings | ✅ | ✅ |
41
+ | Manual ICS file import | ✅ | ❌ |
42
+ | Scheduled ICS import from HTTPS URLs | ✅ | ❌ |
43
+ | External ICS export links | ✅ | ❌ |
44
+ | Create Todo reminders from ICS alarms | ✅ | ❌ |
45
+
46
+ Reminder notes created on desktop can sync to mobile and use Joplin's normal mobile notifications.
47
+
48
+ ## Install
49
+
50
+ My Calendar requires Joplin 3.3 or later.
51
+
52
+ 1. Open Joplin.
53
+ 2. Go to **Tools > Options > Plugins** on Windows/Linux or **Joplin > Settings > Plugins** on macOS.
54
+ 3. Search for **My Calendar**.
55
+ 4. Select **Install**, then restart Joplin.
56
+
57
+ On desktop, use **Toggle My Calendar** from the View or Tools menu to show or hide the panel. The default shortcut is
58
+ `Ctrl+Alt+C`. On mobile, open the plugin from Joplin's plugin menu.
59
+
60
+ ## Create an event
61
+
62
+ ### Use the form
63
+
64
+ 1. Open the **My Calendar** panel.
65
+ 2. Find **Add event note**.
66
+ 3. Choose a notebook.
67
+ 4. Enter the event details.
68
+ 5. Select **Create**.
69
+
70
+ The plugin creates a Joplin note, adds the selected tags, opens the note, and refreshes the calendar.
71
+
72
+ The form supports timed and all-day events, timezones, colors, locations, descriptions, searchable tags, repeats, repeat
73
+ end dates, weekdays, month days, and excluded dates. It highlights invalid fields before creating the note.
74
+
75
+ ### Add an event block to a note
76
+
77
+ Add a fenced block like this to any note:
75
78
 
76
79
  ~~~markdown
77
80
  ```mycalendar-event
@@ -83,257 +86,210 @@ location: Conference Room B
83
86
  ```
84
87
  ~~~
85
88
 
86
- The note will immediately appear on your calendar!
89
+ Only `start` is required. If `title` is missing, the note title is used.
87
90
 
88
- > 💡 **Looking for more?** Check the [examples](./examples) folder for more templates, including recurring events and
89
- > all-day appointments.
91
+ You can keep normal text before and after the block. You can also add several event blocks to one note. See the
92
+ [examples](./examples) folder for all-day, recurring, timezone, and multi-event notes.
90
93
 
91
- ---
94
+ ## Event fields
92
95
 
93
- ## 📥 ICS Import System
96
+ | Field | What it does | Example |
97
+ |:------------------|:--------------------------------------------------|:--------------------------|
98
+ | `start` | Event start. Required. | `2026-02-04 10:00+02:00` |
99
+ | `end` | Event end. | `2026-02-04 11:30+02:00` |
100
+ | `title` | Event name. Uses the note title when empty. | `Team meeting` |
101
+ | `description` | Extra text shown in the day list. | `Review the current work` |
102
+ | `location` | Event location. | `Conference Room B` |
103
+ | `color` | Event color in `#RGB` or `#RRGGBB` form. | `#3498db` |
104
+ | `tz` | IANA timezone for a time without an offset. | `America/Toronto` |
105
+ | `all_day` | Marks an event as all-day. | `true` |
106
+ | `repeat` | Repeat rule: daily, weekly, monthly, or yearly. | `weekly` |
107
+ | `repeat_interval` | Repeat every N days, weeks, months, or years. | `2` |
108
+ | `repeat_until` | Last date or time in the repeat series. | `2026-12-31` |
109
+ | `byweekday` | Days for a weekly repeat. | `MO,WE,FR` |
110
+ | `bymonthday` | Day of the month for a monthly repeat. | `15` |
111
+ | `exdate` | Excludes one date from a repeat. Can be repeated. | `2026-03-04` |
112
+ | `valarm` | Alarm data imported from ICS. | `{"trigger":"-PT15M"}` |
113
+ | `uid` | Stable source ID. Usually managed by the plugin. | `event-123` |
114
+ | `recurrence_id` | ID of one changed repeat occurrence. | `20260304T100000Z` |
94
115
 
95
- The plugin features a robust import system designed for performance and reliability.
116
+ `uid`, `recurrence_id`, and `valarm` are mainly used by ICS import. You normally do not need to add them by hand.
96
117
 
97
- ### How to Import:
118
+ ### Dates and timezones
98
119
 
99
- 1. Open the **My Calendar** panel.
100
- 2. Select the **Target Notebook** where you want your events to be stored.
101
- 3. Choose your `*.ics` file and click **Import**.
102
-
103
- ### Smart Features:
104
-
105
- - **Deduplication**: The plugin uses `UID`s from the ICS file. If you import the same file again, it will only update
106
- changed events or skip unchanged ones.
107
- - **Scheduled URL Import (Desktop)**: You can configure one or more HTTPS ICS + notebook pairs and let the plugin
108
- re-import them automatically on a fixed interval. The recommended format is
109
- `https://...ics | Notebook Title ;; https://...ics | Another Notebook`: `;;` separates pairs, and `|` separates the
110
- URL from the notebook title.
111
- - **Local Color Preservation**: By default, if you manually change the color of an imported event in Joplin, subsequent
112
- imports will preserve your custom color.
113
- - **Optimized Automatic Alarms**: If an ICS event has a reminder, the plugin creates a linked "Todo" note in Joplin.
114
- These todos
115
- appear in your standard Joplin tasks and trigger native notifications. The sync process is smart: it only deletes
116
- outdated alarms and creates new ones, minimizing sync traffic.
117
- - **Improved Format Compatibility**: Handles folded ICS lines, multiline descriptions, and escaped values more
118
- reliably.
119
-
120
- ---
121
-
122
- ## 🛠️ Advanced Syntax
123
-
124
- Below is the full list of properties supported inside the ` ```mycalendar-event ` block:
125
-
126
- | Property | Status | Description | Example |
127
- |:------------------|:-------------|:-------------------------------------------------------------------------------------|:-------------------------|
128
- | `start` | **Required** | Start date and time. Mandatory for the event to appear. | `2025-12-18 10:00+02:00` |
129
- | `title` | Optional | Display name. If omitted, the **Joplin note title** will be used. | `Meeting` |
130
- | `end` | Optional | End date and time. If omitted, the event is treated as a point in time (0 duration). | `2025-12-18 11:30+02:00` |
131
- | `tz` | Optional | Timezone (IANA). | `America/Toronto` |
132
- | `color` | Optional | Hex color for the event bar. | `#e74c3c` |
133
- | `location` | Optional | Location string. | `Home Office` |
134
- | `description` | Optional | Extra details (auto-sanitized). | `Check project status.` |
135
- | `repeat` | Optional | `daily`, `weekly`, `monthly`, `yearly` | `weekly` |
136
- | `repeat_interval` | Optional | Frequency (e.g., every 2 weeks). | `2` |
137
- | `repeat_until` | Optional | End date for recurrence (e.g., wrap up series). | `2026-12-31` |
138
- | `byweekday` | Optional | Specific days for weekly repeat. | `MO,WE,FR` |
139
- | `bymonthday` | Optional | Day of the month for monthly repeat. | `15` |
140
- | `all_day` | Optional | Set to `true` for all-day events. | `true` |
141
-
142
- ### 🕒 Supported Time & Timezone Formats
143
-
144
- The calendar supports several ways to specify the time and timezone of your events:
145
-
146
- 1. **With UTC Offset (Recommended)**
147
- Explicitly define the time and its relation to UTC. This time will be automatically converted to your current
148
- device's timezone.
149
- ```text
150
- start: 2026-02-04 10:00+02:00
151
- ```
152
-
153
- 2. **With `tz` Property (IANA)**
154
- Specify the time and the exact IANA Timezone name. The plugin will handle the conversion based on daylight saving
155
- rules.
156
- ```text
157
- start: 2026-02-04 10:00
158
- tz: America/Toronto
159
- ```
160
-
161
- 3. **Floating Local Time**
162
- If no offset or `tz` is provided, the time is considered "floating" and will be shown exactly as written, regardless
163
- of the device's timezone settings.
164
- ```text
165
- start: 2026-02-04 10:00
166
- ```
167
-
168
- ---
169
-
170
- ## ⚙️ Settings
171
-
172
- Customize your experience in the Joplin Settings (`Tools` > `Options` > `My Calendar`):
173
-
174
- ### Calendar
175
-
176
- - **Week starts on**: Choose between **Monday** (default) or **Sunday** for the calendar grid.
177
- - **Show week numbers**: Toggle the display of week numbers alongside the calendar grid. (Default: Disabled).
178
-
179
- ### Day events
180
-
181
- - **Day events view mode**: Show events as one list, or grouped into **Ongoing / Feature / Past** with auto-moves as
182
- time changes. (Default: Single list).
183
- - **Time format**: Choose between **24h** (default) or **12h** (AM/PM) format for event times.
184
- - **Day events auto-refresh**: Set the interval (in minutes) for how often the day's event list updates. (Default: 1
185
- min).
186
- - **Show event timeline**: Show a visual timeline bar under each event in the day list. Disabling this also stops
187
- related UI update timers. (Default: Enabled).
188
- - **Current timeline line color (hex)**: Optional custom color for the current-time line in the day event timeline.
189
- Use `#RGB` or `#RRGGBB`, or leave empty to keep the default color.
190
- - **Default event color (hex)**: Optional default hex color for imported events without `X-COLOR` and for "Day events"
191
- section events without a color.
192
- Use `#RGB` or `#RRGGBB`, or leave empty to keep the built-in default event color.
193
-
194
- ### ICS Import (Desktop only)
195
-
196
- - **Enable ICS import alarms**: If enabled, alarms from ICS files will be imported as Todo notes. If disabled, existing
197
- alarms will be deleted on re-import. (Default: Disabled).
198
- - **ICS import alarm range**: Define how many days into the future (up to 365) the plugin should scan and generate
199
- native Joplin reminders from your ICS files. (Default: 30 days).
200
- - **ICS reminder emoji**: Choose the emoji or short prefix shown at the start of imported reminder note titles.
201
- (Default: `🔔`).
202
- - **Empty trash after alarm cleanup**: If enabled, the plugin will empty the trash after deleting old alarms. **WARNING
203
- **:
204
- This deletes ALL items in the trash. (Default: Disabled).
205
- - **Scheduled ICS import pairs**: Add pairs in the form
206
- `https://...ics | Notebook Title ;; https://...ics | Another Notebook`. Each valid HTTPS ICS link is imported into
207
- its own existing notebook. If the notebook title is missing, invalid, not found, or ambiguous, that pair is skipped.
208
- - **Scheduled ICS import interval**: Choose how often scheduled URL imports run in the background. Allowed range:
209
- **5-1440 minutes**. (Default: 60 minutes).
210
- - **ICS export links**: Add as many quick-access links as you need to your favorite calendar exporters (e.g., Google
211
- Calendar Export URL). These will appear as convenient buttons in the import panel.
212
-
213
- ### Developer
214
-
215
- - **Enable debug logging**: Activates a visible log box and extra console output to help troubleshoot any issues.
216
-
217
- #### Settings Interface
218
-
219
- | Light Theme | Dark Theme |
220
- |:---------------------------------------------------------------:|:-------------------------------------------------------------:|
221
- | ![Light Settings](./assets/screenshots/light_settings_view.png) | ![Dark Settings](./assets/screenshots/dark_settings_view.png) |
120
+ Use one of these forms:
222
121
 
223
- ---
122
+ ```text
123
+ start: 2026-02-04 10:00+02:00
124
+ ```
224
125
 
225
- ## 👨‍💻 Development
126
+ The UTC offset makes the time clear on every device.
226
127
 
227
- ### Commands
128
+ ```text
129
+ start: 2026-02-04 10:00
130
+ tz: America/Toronto
131
+ ```
228
132
 
229
- - `npm run build`: Compile the project.
230
- - `npm pack`: Create the `.jpl` distribution file.
231
- - `npm run pre-pack`: Run the pre-pack validation flow using the stable single-process Jest command before packaging.
232
- - `npm test`: Run the extensive test suite (350+ cases). This now performs Jest process cleanup first and retries once
233
- in `--runInBand` if a worker crashes with `SIGSEGV`.
234
- - `npm run test:stable`: Run Jest in a single process from the start, with cleanup first. Use this for the most stable
235
- pre-release check.
236
- - `npm run lint`: Check code style and common patterns.
237
- - `bash ./scripts/cleanup-jest.sh`: Kill stale Jest worker processes for this repository before rerunning tests.
133
+ The IANA timezone applies the correct daylight-saving rules.
238
134
 
239
- ### Automation Scripts
135
+ ```text
136
+ start: 2026-02-04 10:00
137
+ ```
240
138
 
241
- The project includes helper scripts in the `scripts/` directory to streamline development and release processes.
139
+ Without an offset or `tz`, the value is a local floating time and is shown as written.
242
140
 
243
- #### `scripts/pre-pack.sh`
141
+ ## Import ICS calendars
244
142
 
245
- Ensures code quality before packaging. By default it runs the linter (failing on warnings), the full test suite, and
246
- then creates the package. The test step uses `npm run test:stable` so packaging does not depend on parallel Jest
247
- workers. Security fixes via `npm audit fix --force` are optional and must be enabled explicitly.
143
+ ICS import is available on desktop.
248
144
 
249
- ```bash
250
- npm run pre-pack
251
- ```
145
+ 1. Open the **My Calendar** panel.
146
+ 2. In **ICS import**, choose the target notebook.
147
+ 3. Choose an `.ics` file.
148
+ 4. Select **Import**.
252
149
 
253
- To include forced audit fixes before validation:
150
+ The importer supports common files from Google Calendar, Outlook, Apple Calendar, and other calendar apps. It handles
151
+ all-day events, timezones, repeats, excluded dates, changed or cancelled occurrences, descriptions, colors, and alarms.
254
152
 
255
- ```bash
256
- npm run pre-pack -- --audit-fix
257
- ```
153
+ When you import the same calendar again, the plugin uses event IDs to update existing notes instead of creating copies.
154
+ Text outside the managed event block is kept. You can also choose whether a local event color should be kept.
258
155
 
259
- #### `scripts/cleanup-jest.sh`
156
+ ### Scheduled import
260
157
 
261
- Finds and terminates stale `jest`, `jest-worker`, and `processChild.js` processes whose working directory belongs to
262
- this repository. This is useful when a previous Jest run leaves worker processes behind after a crash.
158
+ On desktop, the plugin can download and import ICS files from HTTPS URLs. Add pairs in **My Calendar settings**:
263
159
 
264
- ```bash
265
- bash ./scripts/cleanup-jest.sh
160
+ ```text
161
+ https://example.com/calendar.ics | Work ;; https://example.com/home.ics | Personal
266
162
  ```
267
163
 
268
- #### `scripts/run-tests.sh`
164
+ `;;` separates entries. `|` separates the URL from the exact notebook title. The interval can be set from 5 to 1440
165
+ minutes. Use the download button in the calendar toolbar to run all scheduled imports now.
269
166
 
270
- Wrapper used by `npm test`. It runs `scripts/cleanup-jest.sh`, starts the normal parallel Jest run, and if Jest reports
271
- that a worker died with `signal=SIGSEGV`, it performs cleanup again and retries once with `--runInBand`.
167
+ ### ICS alarm reminders
272
168
 
273
- For a fully serial run without the initial parallel attempt, use:
169
+ ICS alarms can be turned into Joplin Todo notes on desktop. You can set:
274
170
 
275
- ```bash
276
- npm run test:stable
277
- ```
171
+ - whether alarm import is enabled;
172
+ - how many days ahead to create reminders;
173
+ - the emoji or short prefix used in reminder titles.
278
174
 
279
- #### `scripts/release.sh`
175
+ Re-importing the calendar updates its reminder notes. Reminder notes from other imported calendars are not changed.
280
176
 
281
- Automates the entire release workflow: bumps version, syncs manifest, tags, pushes, and publishes to NPM.
177
+ ### External export links
282
178
 
283
- ```bash
284
- bash ./scripts/release.sh [patch|minor|major];
179
+ The desktop settings can add buttons that open external calendar export pages:
180
+
181
+ ```text
182
+ Google Calendar | https://example.com/export ;; Work Calendar | https://example.com/work
285
183
  ```
286
184
 
287
- #### `scripts/update-demo-ics.py`
185
+ These are shortcuts to websites. The plugin does not upload your notes or calendar data to them.
186
+
187
+ ## Settings
188
+
189
+ Open **Tools > Options > My Calendar** on Windows/Linux or **Joplin > Settings > My Calendar** on macOS.
190
+
191
+ - **Calendar:** first day of the week and week numbers.
192
+ - **Day events:** single or grouped list, completed Todo markers, 12/24-hour time, refresh interval, and timeline
193
+ visibility.
194
+ - **Colors:** default event colors and current-time line colors for light and dark themes.
195
+ - **ICS import (desktop):** alarms, reminder range, reminder prefix, scheduled imports, and external export links.
196
+ - **Developer:** extra logs in the panel and console.
197
+
198
+ Color settings accept `#RGB` and `#RRGGBB`.
199
+
200
+ | Light theme | Dark theme |
201
+ |:---------------------------------------------------------------:|:-------------------------------------------------------------:|
202
+ | ![Light Settings](./assets/screenshots/light_settings_view.png) | ![Dark Settings](./assets/screenshots/dark_settings_view.png) |
288
203
 
289
- Automatically shifts dates in the demo ICS file to start from today. Useful for refreshing screenshots.
204
+ ## Privacy and safety
205
+
206
+ - Events stay in Joplin notes.
207
+ - The plugin uses Joplin sync and does not need its own server.
208
+ - Scheduled ICS import connects only to the HTTPS URLs you add.
209
+ - Event text is cleaned before it is shown in the panel.
210
+ - External links are limited to HTTP and HTTPS addresses.
211
+
212
+ ## Development
213
+
214
+ ### Project structure
215
+
216
+ - `src/main/`: plugin backend, parsers, services, settings, views, and the UI bridge.
217
+ - `src/ui/`: JavaScript and CSS for the calendar panel.
218
+ - `src/index.ts`: plugin entry point.
219
+ - `tests/`: Jest tests arranged to match the source folders.
220
+ - `examples/`: sample event notes and ICS files.
221
+ - `dist/` and `publish/`: generated build output. Do not edit them by hand.
222
+
223
+ ### Commands
290
224
 
291
225
  ```bash
292
- ./scripts/update-demo-ics.py;
226
+ npm install
227
+ npm run build
228
+ npm run build:jpl
229
+ npm test
230
+ npm run test:stable
231
+ npm run test:watch
232
+ npm run lint
293
233
  ```
294
234
 
295
- #### `scripts/check-tests.sh`
235
+ - `npm run build` builds `dist/index.js`.
236
+ - `npm run build:jpl` creates the `.jpl` package in `publish/`.
237
+ - `npm test` cleans old Jest workers, runs the test suite, and retries once in serial mode after a worker `SIGSEGV`.
238
+ - `npm run test:stable` runs Jest serially from the start.
239
+ - `npm run test:watch` runs Jest in watch mode.
240
+ - `npm run lint` checks source and test files.
296
241
 
297
- Verifies that tests have passed recently (within the last hour) before allowing critical operations.
242
+ ### Automation scripts
243
+
244
+ #### `scripts/pre-pack.sh`
245
+
246
+ Runs lint with no warnings allowed, runs the stable test suite, and builds the package. It also creates the npm tarball.
247
+ Security fixes are opt-in.
298
248
 
299
249
  ```bash
300
- bash ./scripts/check-tests.sh;
250
+ npm run pre-pack
251
+ npm run pre-pack -- --audit-fix
301
252
  ```
302
253
 
303
- #### `scripts/preview-changelog.sh`
254
+ #### `scripts/deploy-and-restart-joplin-dev.sh`
304
255
 
305
- Previews the changelog generation in dry-run mode without modifying files.
256
+ Builds the plugin, copies the `.jpl` file to the local snap installation, restarts Joplin, opens Joplin DevTools, and
257
+ opens Chromium at `chrome://inspect/#devices`.
306
258
 
307
259
  ```bash
308
- bash ./scripts/preview-changelog.sh [patch|minor|major];
260
+ bash ./scripts/deploy-and-restart-joplin-dev.sh
309
261
  ```
310
262
 
311
- ### Development Workflow
312
-
313
- For a detailed guide on branch naming, commit message formats, and the release process, please see the *
314
- *[Development Workflow Guide](./docs/WORKFLOW.md)**.
263
+ This script is specific to the Linux/X11 workstation where its menu coordinates were captured. It requires snap Joplin,
264
+ `xdotool`, `xprop`, and Chromium. It closes the current Joplin session and replaces the installed development copy of
265
+ the plugin.
315
266
 
316
- ### Security First:
267
+ #### Test helpers
317
268
 
318
- The code implements strict sanitization to ensure that imported calendar data cannot execute arbitrary Markdown or break
319
- the Joplin interface.
269
+ - `scripts/run-tests.sh` cleans stale Jest processes and retries a crashed parallel run once with `--runInBand`.
270
+ - `scripts/cleanup-jest.sh` removes stale Jest workers for this repository.
271
+ - `scripts/check-tests.sh` checks that the latest successful test run is no more than one hour old.
320
272
 
321
- ## ❤️ Support
273
+ #### Release helpers
322
274
 
323
- If you find this plugin useful, please consider supporting its development. Your donations help me dedicate more time to
324
- maintaining the project and adding new features.
275
+ - `scripts/release.sh [patch|minor|major]` validates GitHub and npm access, versions the package, builds it, creates the
276
+ GitHub release, and publishes the npm tarball.
277
+ - `scripts/preview-changelog.sh [patch|minor|major]` previews generated release notes without changing files.
278
+ - `scripts/update-demo-ics.py` moves dates in the demo ICS file forward for screenshots and testing.
325
279
 
326
- - **[Donate via PayPal](https://www.paypal.me/volodymyroliinykca)** - support the development of **My Calendar**.
280
+ See the [Development Workflow Guide](./docs/WORKFLOW.md) for branch names, commit messages, and releases.
327
281
 
328
- Every coffee counts. Thank you! ☕
282
+ ## Support
329
283
 
330
- ---
284
+ If My Calendar is useful to you, you
285
+ can [support its development with PayPal](https://www.paypal.me/volodymyroliinykca).
331
286
 
332
- ## 📜 Changelog
287
+ ## Changelog
333
288
 
334
- Detailed changes for each release are documented in the [CHANGELOG](./CHANGELOG.md).
289
+ See [CHANGELOG.md](./CHANGELOG.md) for release notes.
335
290
 
336
- ## 📄 License
291
+ ## License
337
292
 
338
293
  Copyright (c) 2024-2026 Volodymyr Oliinyk.
339
- Licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details.
294
+
295
+ Licensed under the [MIT License](LICENSE).