@fullcalendar/icalendar 5.10.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/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Adam Shaw
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+
2
+ # FullCalendar iCalendar Plugin
3
+
4
+ Fetch events from a public iCalendar / .ics feed
5
+
6
+ [View the docs »](https://fullcalendar.io/docs/icalendar)
7
+
8
+ This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar)
package/main.cjs.js ADDED
@@ -0,0 +1,271 @@
1
+ /*!
2
+ FullCalendar v5.10.0
3
+ Docs & License: https://fullcalendar.io/
4
+ (c) 2021 Adam Shaw
5
+ */
6
+ 'use strict';
7
+
8
+ Object.defineProperty(exports, '__esModule', { value: true });
9
+
10
+ var tslib = require('tslib');
11
+ var common = require('@fullcalendar/common');
12
+ var ICAL = require('ical.js');
13
+
14
+ function _interopNamespace(e) {
15
+ if (e && e.__esModule) return e;
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () {
24
+ return e[k];
25
+ }
26
+ });
27
+ }
28
+ });
29
+ }
30
+ n['default'] = e;
31
+ return Object.freeze(n);
32
+ }
33
+
34
+ var ICAL__namespace = /*#__PURE__*/_interopNamespace(ICAL);
35
+
36
+ /* eslint-disable */
37
+ var IcalExpander = /** @class */ (function () {
38
+ function IcalExpander(opts) {
39
+ this.maxIterations = opts.maxIterations != null ? opts.maxIterations : 1000;
40
+ this.skipInvalidDates = opts.skipInvalidDates != null ? opts.skipInvalidDates : false;
41
+ this.jCalData = ICAL__namespace.parse(opts.ics);
42
+ this.component = new ICAL__namespace.Component(this.jCalData);
43
+ this.events = this.component.getAllSubcomponents('vevent').map(function (vevent) { return new ICAL__namespace.Event(vevent); });
44
+ if (this.skipInvalidDates) {
45
+ this.events = this.events.filter(function (evt) {
46
+ try {
47
+ evt.startDate.toJSDate();
48
+ evt.endDate.toJSDate();
49
+ return true;
50
+ }
51
+ catch (err) {
52
+ // skipping events with invalid time
53
+ return false;
54
+ }
55
+ });
56
+ }
57
+ }
58
+ IcalExpander.prototype.between = function (after, before) {
59
+ var _this = this;
60
+ function isEventWithinRange(startTime, endTime) {
61
+ return (!after || endTime >= after.getTime()) &&
62
+ (!before || startTime <= before.getTime());
63
+ }
64
+ function getTimes(eventOrOccurrence) {
65
+ var startTime = eventOrOccurrence.startDate.toJSDate().getTime();
66
+ var endTime = eventOrOccurrence.endDate.toJSDate().getTime();
67
+ // If it is an all day event, the end date is set to 00:00 of the next day
68
+ // So we need to make it be 23:59:59 to compare correctly with the given range
69
+ if (eventOrOccurrence.endDate.isDate && (endTime > startTime)) {
70
+ endTime -= 1;
71
+ }
72
+ return { startTime: startTime, endTime: endTime };
73
+ }
74
+ var exceptions = [];
75
+ this.events.forEach(function (event) {
76
+ if (event.isRecurrenceException())
77
+ exceptions.push(event);
78
+ });
79
+ var ret = {
80
+ events: [],
81
+ occurrences: [],
82
+ };
83
+ this.events.filter(function (e) { return !e.isRecurrenceException(); }).forEach(function (event) {
84
+ var exdates = [];
85
+ event.component.getAllProperties('exdate').forEach(function (exdateProp) {
86
+ var exdate = exdateProp.getFirstValue();
87
+ exdates.push(exdate.toJSDate().getTime());
88
+ });
89
+ // Recurring event is handled differently
90
+ if (event.isRecurring()) {
91
+ var iterator = event.iterator();
92
+ var next = void 0;
93
+ var i = 0;
94
+ var _loop_1 = function () {
95
+ i += 1;
96
+ next = iterator.next();
97
+ if (next) {
98
+ var occurrence_1 = event.getOccurrenceDetails(next);
99
+ var _b = getTimes(occurrence_1), startTime_1 = _b.startTime, endTime_1 = _b.endTime;
100
+ var isOccurrenceExcluded = exdates.indexOf(startTime_1) !== -1;
101
+ // TODO check that within same day?
102
+ var exception = exceptions.find(function (ex) { return ex.uid === event.uid && ex.recurrenceId.toJSDate().getTime() === occurrence_1.startDate.toJSDate().getTime(); });
103
+ // We have passed the max date, stop
104
+ if (before && startTime_1 > before.getTime())
105
+ return "break";
106
+ // Check that we are within our range
107
+ if (isEventWithinRange(startTime_1, endTime_1)) {
108
+ if (exception) {
109
+ ret.events.push(exception);
110
+ }
111
+ else if (!isOccurrenceExcluded) {
112
+ ret.occurrences.push(occurrence_1);
113
+ }
114
+ }
115
+ }
116
+ };
117
+ do {
118
+ var state_1 = _loop_1();
119
+ if (state_1 === "break")
120
+ break;
121
+ } while (next && (!_this.maxIterations || i < _this.maxIterations));
122
+ return;
123
+ }
124
+ // Non-recurring event:
125
+ var _a = getTimes(event), startTime = _a.startTime, endTime = _a.endTime;
126
+ if (isEventWithinRange(startTime, endTime))
127
+ ret.events.push(event);
128
+ });
129
+ return ret;
130
+ };
131
+ IcalExpander.prototype.before = function (before) {
132
+ return this.between(undefined, before);
133
+ };
134
+ IcalExpander.prototype.after = function (after) {
135
+ return this.between(after);
136
+ };
137
+ IcalExpander.prototype.all = function () {
138
+ return this.between();
139
+ };
140
+ return IcalExpander;
141
+ }());
142
+
143
+ var eventSourceDef = {
144
+ parseMeta: function (refined) {
145
+ if (refined.url && refined.format === 'ics') {
146
+ return {
147
+ url: refined.url,
148
+ format: 'ics',
149
+ };
150
+ }
151
+ return null;
152
+ },
153
+ fetch: function (arg, onSuccess, onFailure) {
154
+ var meta = arg.eventSource.meta;
155
+ var internalState = meta.internalState;
156
+ function handleICalEvents(errorMessage, iCalExpander, xhr) {
157
+ if (errorMessage) {
158
+ onFailure({ message: errorMessage, xhr: xhr });
159
+ }
160
+ else {
161
+ onSuccess({ rawEvents: expandICalEvents(iCalExpander, arg.range), xhr: xhr });
162
+ }
163
+ }
164
+ /*
165
+ NOTE: isRefetch is a HACK. we would do the recurring-expanding in a separate plugin hook,
166
+ but we couldn't leverage built-in allDay-guessing, among other things.
167
+ */
168
+ if (!internalState || arg.isRefetch) {
169
+ internalState = meta.internalState = {
170
+ completed: false,
171
+ callbacks: [handleICalEvents],
172
+ errorMessage: '',
173
+ iCalExpander: null,
174
+ xhr: null,
175
+ };
176
+ requestICal(meta.url, function (rawFeed, xhr) {
177
+ var iCalExpander = new IcalExpander({
178
+ ics: rawFeed,
179
+ skipInvalidDates: true,
180
+ });
181
+ for (var _i = 0, _a = internalState.callbacks; _i < _a.length; _i++) {
182
+ var callback = _a[_i];
183
+ callback('', iCalExpander, xhr);
184
+ }
185
+ internalState.completed = true;
186
+ internalState.callbacks = [];
187
+ internalState.iCalExpander = iCalExpander;
188
+ internalState.xhr = xhr;
189
+ }, function (errorMessage, xhr) {
190
+ for (var _i = 0, _a = internalState.callbacks; _i < _a.length; _i++) {
191
+ var callback = _a[_i];
192
+ callback(errorMessage, null, xhr);
193
+ }
194
+ internalState.completed = true;
195
+ internalState.callbacks = [];
196
+ internalState.errorMessage = errorMessage;
197
+ internalState.xhr = xhr;
198
+ });
199
+ }
200
+ else if (!internalState.completed) {
201
+ internalState.callbacks.push(handleICalEvents);
202
+ }
203
+ else {
204
+ handleICalEvents(internalState.errorMessage, internalState.iCalExpander, internalState.xhr);
205
+ }
206
+ },
207
+ };
208
+ function requestICal(url, successCallback, failureCallback) {
209
+ var xhr = new XMLHttpRequest();
210
+ xhr.open('GET', url, true);
211
+ xhr.onload = function () {
212
+ if (xhr.status >= 200 && xhr.status < 400) {
213
+ successCallback(xhr.responseText, xhr);
214
+ }
215
+ else {
216
+ failureCallback('Request failed', xhr);
217
+ }
218
+ };
219
+ xhr.onerror = function () { return failureCallback('Request failed', xhr); };
220
+ xhr.send(null);
221
+ }
222
+ function expandICalEvents(iCalExpander, range) {
223
+ // expand the range. because our `range` is timeZone-agnostic UTC
224
+ // or maybe because ical.js always produces dates in local time? i forget
225
+ var rangeStart = common.addDays(range.start, -1);
226
+ var rangeEnd = common.addDays(range.end, 1);
227
+ var iCalRes = iCalExpander.between(rangeStart, rangeEnd); // end inclusive. will give extra results
228
+ var expanded = [];
229
+ // TODO: instead of using startDate/endDate.toString to communicate allDay,
230
+ // we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.
231
+ // single events
232
+ for (var _i = 0, _a = iCalRes.events; _i < _a.length; _i++) {
233
+ var iCalEvent = _a[_i];
234
+ expanded.push(tslib.__assign(tslib.__assign({}, buildNonDateProps(iCalEvent)), { start: iCalEvent.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)
235
+ ? iCalEvent.endDate.toString()
236
+ : null }));
237
+ }
238
+ // recurring event instances
239
+ for (var _b = 0, _c = iCalRes.occurrences; _b < _c.length; _b++) {
240
+ var iCalOccurence = _c[_b];
241
+ var iCalEvent = iCalOccurence.item;
242
+ expanded.push(tslib.__assign(tslib.__assign({}, buildNonDateProps(iCalEvent)), { start: iCalOccurence.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)
243
+ ? iCalOccurence.endDate.toString()
244
+ : null }));
245
+ }
246
+ return expanded;
247
+ }
248
+ function buildNonDateProps(iCalEvent) {
249
+ return {
250
+ title: iCalEvent.summary,
251
+ url: extractEventUrl(iCalEvent),
252
+ extendedProps: {
253
+ location: iCalEvent.location,
254
+ organizer: iCalEvent.organizer,
255
+ description: iCalEvent.description,
256
+ },
257
+ };
258
+ }
259
+ function extractEventUrl(iCalEvent) {
260
+ var urlProp = iCalEvent.component.getFirstProperty('url');
261
+ return urlProp ? urlProp.getFirstValue() : '';
262
+ }
263
+ function specifiesEnd(iCalEvent) {
264
+ return Boolean(iCalEvent.component.getFirstProperty('dtend')) ||
265
+ Boolean(iCalEvent.component.getFirstProperty('duration'));
266
+ }
267
+ var main = common.createPlugin({
268
+ eventSourceDefs: [eventSourceDef],
269
+ });
270
+
271
+ exports.default = main;
package/main.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import * as _fullcalendar_common from '@fullcalendar/common';
2
+
3
+ declare const _default: _fullcalendar_common.PluginDef;
4
+
5
+
6
+ export default _default;
package/main.global.js ADDED
@@ -0,0 +1,300 @@
1
+ /*!
2
+ FullCalendar v5.10.0
3
+ Docs & License: https://fullcalendar.io/
4
+ (c) 2021 Adam Shaw
5
+ */
6
+ var FullCalendarICalendar = (function (exports, common, ICAL) {
7
+ 'use strict';
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () {
19
+ return e[k];
20
+ }
21
+ });
22
+ }
23
+ });
24
+ }
25
+ n['default'] = e;
26
+ return Object.freeze(n);
27
+ }
28
+
29
+ var ICAL__namespace = /*#__PURE__*/_interopNamespace(ICAL);
30
+
31
+ /*! *****************************************************************************
32
+ Copyright (c) Microsoft Corporation.
33
+
34
+ Permission to use, copy, modify, and/or distribute this software for any
35
+ purpose with or without fee is hereby granted.
36
+
37
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
38
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
40
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
41
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
42
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
43
+ PERFORMANCE OF THIS SOFTWARE.
44
+ ***************************************************************************** */
45
+
46
+ var __assign = function() {
47
+ __assign = Object.assign || function __assign(t) {
48
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
49
+ s = arguments[i];
50
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
51
+ }
52
+ return t;
53
+ };
54
+ return __assign.apply(this, arguments);
55
+ };
56
+
57
+ /* eslint-disable */
58
+ var IcalExpander = /** @class */ (function () {
59
+ function IcalExpander(opts) {
60
+ this.maxIterations = opts.maxIterations != null ? opts.maxIterations : 1000;
61
+ this.skipInvalidDates = opts.skipInvalidDates != null ? opts.skipInvalidDates : false;
62
+ this.jCalData = ICAL__namespace.parse(opts.ics);
63
+ this.component = new ICAL__namespace.Component(this.jCalData);
64
+ this.events = this.component.getAllSubcomponents('vevent').map(function (vevent) { return new ICAL__namespace.Event(vevent); });
65
+ if (this.skipInvalidDates) {
66
+ this.events = this.events.filter(function (evt) {
67
+ try {
68
+ evt.startDate.toJSDate();
69
+ evt.endDate.toJSDate();
70
+ return true;
71
+ }
72
+ catch (err) {
73
+ // skipping events with invalid time
74
+ return false;
75
+ }
76
+ });
77
+ }
78
+ }
79
+ IcalExpander.prototype.between = function (after, before) {
80
+ var _this = this;
81
+ function isEventWithinRange(startTime, endTime) {
82
+ return (!after || endTime >= after.getTime()) &&
83
+ (!before || startTime <= before.getTime());
84
+ }
85
+ function getTimes(eventOrOccurrence) {
86
+ var startTime = eventOrOccurrence.startDate.toJSDate().getTime();
87
+ var endTime = eventOrOccurrence.endDate.toJSDate().getTime();
88
+ // If it is an all day event, the end date is set to 00:00 of the next day
89
+ // So we need to make it be 23:59:59 to compare correctly with the given range
90
+ if (eventOrOccurrence.endDate.isDate && (endTime > startTime)) {
91
+ endTime -= 1;
92
+ }
93
+ return { startTime: startTime, endTime: endTime };
94
+ }
95
+ var exceptions = [];
96
+ this.events.forEach(function (event) {
97
+ if (event.isRecurrenceException())
98
+ exceptions.push(event);
99
+ });
100
+ var ret = {
101
+ events: [],
102
+ occurrences: [],
103
+ };
104
+ this.events.filter(function (e) { return !e.isRecurrenceException(); }).forEach(function (event) {
105
+ var exdates = [];
106
+ event.component.getAllProperties('exdate').forEach(function (exdateProp) {
107
+ var exdate = exdateProp.getFirstValue();
108
+ exdates.push(exdate.toJSDate().getTime());
109
+ });
110
+ // Recurring event is handled differently
111
+ if (event.isRecurring()) {
112
+ var iterator = event.iterator();
113
+ var next = void 0;
114
+ var i = 0;
115
+ var _loop_1 = function () {
116
+ i += 1;
117
+ next = iterator.next();
118
+ if (next) {
119
+ var occurrence_1 = event.getOccurrenceDetails(next);
120
+ var _b = getTimes(occurrence_1), startTime_1 = _b.startTime, endTime_1 = _b.endTime;
121
+ var isOccurrenceExcluded = exdates.indexOf(startTime_1) !== -1;
122
+ // TODO check that within same day?
123
+ var exception = exceptions.find(function (ex) { return ex.uid === event.uid && ex.recurrenceId.toJSDate().getTime() === occurrence_1.startDate.toJSDate().getTime(); });
124
+ // We have passed the max date, stop
125
+ if (before && startTime_1 > before.getTime())
126
+ return "break";
127
+ // Check that we are within our range
128
+ if (isEventWithinRange(startTime_1, endTime_1)) {
129
+ if (exception) {
130
+ ret.events.push(exception);
131
+ }
132
+ else if (!isOccurrenceExcluded) {
133
+ ret.occurrences.push(occurrence_1);
134
+ }
135
+ }
136
+ }
137
+ };
138
+ do {
139
+ var state_1 = _loop_1();
140
+ if (state_1 === "break")
141
+ break;
142
+ } while (next && (!_this.maxIterations || i < _this.maxIterations));
143
+ return;
144
+ }
145
+ // Non-recurring event:
146
+ var _a = getTimes(event), startTime = _a.startTime, endTime = _a.endTime;
147
+ if (isEventWithinRange(startTime, endTime))
148
+ ret.events.push(event);
149
+ });
150
+ return ret;
151
+ };
152
+ IcalExpander.prototype.before = function (before) {
153
+ return this.between(undefined, before);
154
+ };
155
+ IcalExpander.prototype.after = function (after) {
156
+ return this.between(after);
157
+ };
158
+ IcalExpander.prototype.all = function () {
159
+ return this.between();
160
+ };
161
+ return IcalExpander;
162
+ }());
163
+
164
+ var eventSourceDef = {
165
+ parseMeta: function (refined) {
166
+ if (refined.url && refined.format === 'ics') {
167
+ return {
168
+ url: refined.url,
169
+ format: 'ics',
170
+ };
171
+ }
172
+ return null;
173
+ },
174
+ fetch: function (arg, onSuccess, onFailure) {
175
+ var meta = arg.eventSource.meta;
176
+ var internalState = meta.internalState;
177
+ function handleICalEvents(errorMessage, iCalExpander, xhr) {
178
+ if (errorMessage) {
179
+ onFailure({ message: errorMessage, xhr: xhr });
180
+ }
181
+ else {
182
+ onSuccess({ rawEvents: expandICalEvents(iCalExpander, arg.range), xhr: xhr });
183
+ }
184
+ }
185
+ /*
186
+ NOTE: isRefetch is a HACK. we would do the recurring-expanding in a separate plugin hook,
187
+ but we couldn't leverage built-in allDay-guessing, among other things.
188
+ */
189
+ if (!internalState || arg.isRefetch) {
190
+ internalState = meta.internalState = {
191
+ completed: false,
192
+ callbacks: [handleICalEvents],
193
+ errorMessage: '',
194
+ iCalExpander: null,
195
+ xhr: null,
196
+ };
197
+ requestICal(meta.url, function (rawFeed, xhr) {
198
+ var iCalExpander = new IcalExpander({
199
+ ics: rawFeed,
200
+ skipInvalidDates: true,
201
+ });
202
+ for (var _i = 0, _a = internalState.callbacks; _i < _a.length; _i++) {
203
+ var callback = _a[_i];
204
+ callback('', iCalExpander, xhr);
205
+ }
206
+ internalState.completed = true;
207
+ internalState.callbacks = [];
208
+ internalState.iCalExpander = iCalExpander;
209
+ internalState.xhr = xhr;
210
+ }, function (errorMessage, xhr) {
211
+ for (var _i = 0, _a = internalState.callbacks; _i < _a.length; _i++) {
212
+ var callback = _a[_i];
213
+ callback(errorMessage, null, xhr);
214
+ }
215
+ internalState.completed = true;
216
+ internalState.callbacks = [];
217
+ internalState.errorMessage = errorMessage;
218
+ internalState.xhr = xhr;
219
+ });
220
+ }
221
+ else if (!internalState.completed) {
222
+ internalState.callbacks.push(handleICalEvents);
223
+ }
224
+ else {
225
+ handleICalEvents(internalState.errorMessage, internalState.iCalExpander, internalState.xhr);
226
+ }
227
+ },
228
+ };
229
+ function requestICal(url, successCallback, failureCallback) {
230
+ var xhr = new XMLHttpRequest();
231
+ xhr.open('GET', url, true);
232
+ xhr.onload = function () {
233
+ if (xhr.status >= 200 && xhr.status < 400) {
234
+ successCallback(xhr.responseText, xhr);
235
+ }
236
+ else {
237
+ failureCallback('Request failed', xhr);
238
+ }
239
+ };
240
+ xhr.onerror = function () { return failureCallback('Request failed', xhr); };
241
+ xhr.send(null);
242
+ }
243
+ function expandICalEvents(iCalExpander, range) {
244
+ // expand the range. because our `range` is timeZone-agnostic UTC
245
+ // or maybe because ical.js always produces dates in local time? i forget
246
+ var rangeStart = common.addDays(range.start, -1);
247
+ var rangeEnd = common.addDays(range.end, 1);
248
+ var iCalRes = iCalExpander.between(rangeStart, rangeEnd); // end inclusive. will give extra results
249
+ var expanded = [];
250
+ // TODO: instead of using startDate/endDate.toString to communicate allDay,
251
+ // we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.
252
+ // single events
253
+ for (var _i = 0, _a = iCalRes.events; _i < _a.length; _i++) {
254
+ var iCalEvent = _a[_i];
255
+ expanded.push(__assign(__assign({}, buildNonDateProps(iCalEvent)), { start: iCalEvent.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)
256
+ ? iCalEvent.endDate.toString()
257
+ : null }));
258
+ }
259
+ // recurring event instances
260
+ for (var _b = 0, _c = iCalRes.occurrences; _b < _c.length; _b++) {
261
+ var iCalOccurence = _c[_b];
262
+ var iCalEvent = iCalOccurence.item;
263
+ expanded.push(__assign(__assign({}, buildNonDateProps(iCalEvent)), { start: iCalOccurence.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)
264
+ ? iCalOccurence.endDate.toString()
265
+ : null }));
266
+ }
267
+ return expanded;
268
+ }
269
+ function buildNonDateProps(iCalEvent) {
270
+ return {
271
+ title: iCalEvent.summary,
272
+ url: extractEventUrl(iCalEvent),
273
+ extendedProps: {
274
+ location: iCalEvent.location,
275
+ organizer: iCalEvent.organizer,
276
+ description: iCalEvent.description,
277
+ },
278
+ };
279
+ }
280
+ function extractEventUrl(iCalEvent) {
281
+ var urlProp = iCalEvent.component.getFirstProperty('url');
282
+ return urlProp ? urlProp.getFirstValue() : '';
283
+ }
284
+ function specifiesEnd(iCalEvent) {
285
+ return Boolean(iCalEvent.component.getFirstProperty('dtend')) ||
286
+ Boolean(iCalEvent.component.getFirstProperty('duration'));
287
+ }
288
+ var plugin = common.createPlugin({
289
+ eventSourceDefs: [eventSourceDef],
290
+ });
291
+
292
+ common.globalPlugins.push(plugin);
293
+
294
+ exports.default = plugin;
295
+
296
+ Object.defineProperty(exports, '__esModule', { value: true });
297
+
298
+ return exports;
299
+
300
+ }({}, FullCalendar, ICAL));
@@ -0,0 +1,6 @@
1
+ /*!
2
+ FullCalendar v5.10.0
3
+ Docs & License: https://fullcalendar.io/
4
+ (c) 2021 Adam Shaw
5
+ */
6
+ var FullCalendarICalendar=function(e,t,n){"use strict";function r(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var a=r(n),i=function(){return(i=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var a in t=arguments[n])Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e}).apply(this,arguments)},o=function(){function e(e){this.maxIterations=null!=e.maxIterations?e.maxIterations:1e3,this.skipInvalidDates=null!=e.skipInvalidDates&&e.skipInvalidDates,this.jCalData=a.parse(e.ics),this.component=new a.Component(this.jCalData),this.events=this.component.getAllSubcomponents("vevent").map((function(e){return new a.Event(e)})),this.skipInvalidDates&&(this.events=this.events.filter((function(e){try{return e.startDate.toJSDate(),e.endDate.toJSDate(),!0}catch(e){return!1}})))}return e.prototype.between=function(e,t){var n=this;function r(n,r){return(!e||r>=e.getTime())&&(!t||n<=t.getTime())}function a(e){var t=e.startDate.toJSDate().getTime(),n=e.endDate.toJSDate().getTime();return e.endDate.isDate&&n>t&&(n-=1),{startTime:t,endTime:n}}var i=[];this.events.forEach((function(e){e.isRecurrenceException()&&i.push(e)}));var o={events:[],occurrences:[]};return this.events.filter((function(e){return!e.isRecurrenceException()})).forEach((function(e){var s=[];if(e.component.getAllProperties("exdate").forEach((function(e){var t=e.getFirstValue();s.push(t.toJSDate().getTime())})),e.isRecurring()){var u=e.iterator(),c=void 0,l=0,f=function(){if(l+=1,c=u.next()){var n=e.getOccurrenceDetails(c),f=a(n),p=f.startTime,d=f.endTime,v=-1!==s.indexOf(p),h=i.find((function(t){return t.uid===e.uid&&t.recurrenceId.toJSDate().getTime()===n.startDate.toJSDate().getTime()}));if(t&&p>t.getTime())return"break";r(p,d)&&(h?o.events.push(h):v||o.occurrences.push(n))}};do{if("break"===f())break}while(c&&(!n.maxIterations||l<n.maxIterations))}else{var p=a(e);r(p.startTime,p.endTime)&&o.events.push(e)}})),o},e.prototype.before=function(e){return this.between(void 0,e)},e.prototype.after=function(e){return this.between(e)},e.prototype.all=function(){return this.between()},e}(),s={parseMeta:function(e){return e.url&&"ics"===e.format?{url:e.url,format:"ics"}:null},fetch:function(e,t,n){var r,a,i,s,c=e.eventSource.meta,l=c.internalState;function f(r,a,i){r?n({message:r,xhr:i}):t({rawEvents:u(a,e.range),xhr:i})}!l||e.isRefetch?(l=c.internalState={completed:!1,callbacks:[f],errorMessage:"",iCalExpander:null,xhr:null},r=c.url,a=function(e,t){for(var n=new o({ics:e,skipInvalidDates:!0}),r=0,a=l.callbacks;r<a.length;r++)(0,a[r])("",n,t);l.completed=!0,l.callbacks=[],l.iCalExpander=n,l.xhr=t},i=function(e,t){for(var n=0,r=l.callbacks;n<r.length;n++)(0,r[n])(e,null,t);l.completed=!0,l.callbacks=[],l.errorMessage=e,l.xhr=t},(s=new XMLHttpRequest).open("GET",r,!0),s.onload=function(){s.status>=200&&s.status<400?a(s.responseText,s):i("Request failed",s)},s.onerror=function(){return i("Request failed",s)},s.send(null)):l.completed?f(l.errorMessage,l.iCalExpander,l.xhr):l.callbacks.push(f)}};function u(e,n){for(var r=t.addDays(n.start,-1),a=t.addDays(n.end,1),o=e.between(r,a),s=[],u=0,l=o.events;u<l.length;u++){var p=l[u];s.push(i(i({},c(p)),{start:p.startDate.toString(),end:f(p)&&p.endDate?p.endDate.toString():null}))}for(var d=0,v=o.occurrences;d<v.length;d++){var h=v[d];p=h.item;s.push(i(i({},c(p)),{start:h.startDate.toString(),end:f(p)&&h.endDate?h.endDate.toString():null}))}return s}function c(e){return{title:e.summary,url:l(e),extendedProps:{location:e.location,organizer:e.organizer,description:e.description}}}function l(e){var t=e.component.getFirstProperty("url");return t?t.getFirstValue():""}function f(e){return Boolean(e.component.getFirstProperty("dtend"))||Boolean(e.component.getFirstProperty("duration"))}var p=t.createPlugin({eventSourceDefs:[s]});return t.globalPlugins.push(p),e.default=p,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,ICAL);
package/main.js ADDED
@@ -0,0 +1,246 @@
1
+ /*!
2
+ FullCalendar v5.10.0
3
+ Docs & License: https://fullcalendar.io/
4
+ (c) 2021 Adam Shaw
5
+ */
6
+ import { __assign } from 'tslib';
7
+ import { createPlugin, addDays } from '@fullcalendar/common';
8
+ import * as ICAL from 'ical.js';
9
+
10
+ /* eslint-disable */
11
+ var IcalExpander = /** @class */ (function () {
12
+ function IcalExpander(opts) {
13
+ this.maxIterations = opts.maxIterations != null ? opts.maxIterations : 1000;
14
+ this.skipInvalidDates = opts.skipInvalidDates != null ? opts.skipInvalidDates : false;
15
+ this.jCalData = ICAL.parse(opts.ics);
16
+ this.component = new ICAL.Component(this.jCalData);
17
+ this.events = this.component.getAllSubcomponents('vevent').map(function (vevent) { return new ICAL.Event(vevent); });
18
+ if (this.skipInvalidDates) {
19
+ this.events = this.events.filter(function (evt) {
20
+ try {
21
+ evt.startDate.toJSDate();
22
+ evt.endDate.toJSDate();
23
+ return true;
24
+ }
25
+ catch (err) {
26
+ // skipping events with invalid time
27
+ return false;
28
+ }
29
+ });
30
+ }
31
+ }
32
+ IcalExpander.prototype.between = function (after, before) {
33
+ var _this = this;
34
+ function isEventWithinRange(startTime, endTime) {
35
+ return (!after || endTime >= after.getTime()) &&
36
+ (!before || startTime <= before.getTime());
37
+ }
38
+ function getTimes(eventOrOccurrence) {
39
+ var startTime = eventOrOccurrence.startDate.toJSDate().getTime();
40
+ var endTime = eventOrOccurrence.endDate.toJSDate().getTime();
41
+ // If it is an all day event, the end date is set to 00:00 of the next day
42
+ // So we need to make it be 23:59:59 to compare correctly with the given range
43
+ if (eventOrOccurrence.endDate.isDate && (endTime > startTime)) {
44
+ endTime -= 1;
45
+ }
46
+ return { startTime: startTime, endTime: endTime };
47
+ }
48
+ var exceptions = [];
49
+ this.events.forEach(function (event) {
50
+ if (event.isRecurrenceException())
51
+ exceptions.push(event);
52
+ });
53
+ var ret = {
54
+ events: [],
55
+ occurrences: [],
56
+ };
57
+ this.events.filter(function (e) { return !e.isRecurrenceException(); }).forEach(function (event) {
58
+ var exdates = [];
59
+ event.component.getAllProperties('exdate').forEach(function (exdateProp) {
60
+ var exdate = exdateProp.getFirstValue();
61
+ exdates.push(exdate.toJSDate().getTime());
62
+ });
63
+ // Recurring event is handled differently
64
+ if (event.isRecurring()) {
65
+ var iterator = event.iterator();
66
+ var next = void 0;
67
+ var i = 0;
68
+ var _loop_1 = function () {
69
+ i += 1;
70
+ next = iterator.next();
71
+ if (next) {
72
+ var occurrence_1 = event.getOccurrenceDetails(next);
73
+ var _b = getTimes(occurrence_1), startTime_1 = _b.startTime, endTime_1 = _b.endTime;
74
+ var isOccurrenceExcluded = exdates.indexOf(startTime_1) !== -1;
75
+ // TODO check that within same day?
76
+ var exception = exceptions.find(function (ex) { return ex.uid === event.uid && ex.recurrenceId.toJSDate().getTime() === occurrence_1.startDate.toJSDate().getTime(); });
77
+ // We have passed the max date, stop
78
+ if (before && startTime_1 > before.getTime())
79
+ return "break";
80
+ // Check that we are within our range
81
+ if (isEventWithinRange(startTime_1, endTime_1)) {
82
+ if (exception) {
83
+ ret.events.push(exception);
84
+ }
85
+ else if (!isOccurrenceExcluded) {
86
+ ret.occurrences.push(occurrence_1);
87
+ }
88
+ }
89
+ }
90
+ };
91
+ do {
92
+ var state_1 = _loop_1();
93
+ if (state_1 === "break")
94
+ break;
95
+ } while (next && (!_this.maxIterations || i < _this.maxIterations));
96
+ return;
97
+ }
98
+ // Non-recurring event:
99
+ var _a = getTimes(event), startTime = _a.startTime, endTime = _a.endTime;
100
+ if (isEventWithinRange(startTime, endTime))
101
+ ret.events.push(event);
102
+ });
103
+ return ret;
104
+ };
105
+ IcalExpander.prototype.before = function (before) {
106
+ return this.between(undefined, before);
107
+ };
108
+ IcalExpander.prototype.after = function (after) {
109
+ return this.between(after);
110
+ };
111
+ IcalExpander.prototype.all = function () {
112
+ return this.between();
113
+ };
114
+ return IcalExpander;
115
+ }());
116
+
117
+ var eventSourceDef = {
118
+ parseMeta: function (refined) {
119
+ if (refined.url && refined.format === 'ics') {
120
+ return {
121
+ url: refined.url,
122
+ format: 'ics',
123
+ };
124
+ }
125
+ return null;
126
+ },
127
+ fetch: function (arg, onSuccess, onFailure) {
128
+ var meta = arg.eventSource.meta;
129
+ var internalState = meta.internalState;
130
+ function handleICalEvents(errorMessage, iCalExpander, xhr) {
131
+ if (errorMessage) {
132
+ onFailure({ message: errorMessage, xhr: xhr });
133
+ }
134
+ else {
135
+ onSuccess({ rawEvents: expandICalEvents(iCalExpander, arg.range), xhr: xhr });
136
+ }
137
+ }
138
+ /*
139
+ NOTE: isRefetch is a HACK. we would do the recurring-expanding in a separate plugin hook,
140
+ but we couldn't leverage built-in allDay-guessing, among other things.
141
+ */
142
+ if (!internalState || arg.isRefetch) {
143
+ internalState = meta.internalState = {
144
+ completed: false,
145
+ callbacks: [handleICalEvents],
146
+ errorMessage: '',
147
+ iCalExpander: null,
148
+ xhr: null,
149
+ };
150
+ requestICal(meta.url, function (rawFeed, xhr) {
151
+ var iCalExpander = new IcalExpander({
152
+ ics: rawFeed,
153
+ skipInvalidDates: true,
154
+ });
155
+ for (var _i = 0, _a = internalState.callbacks; _i < _a.length; _i++) {
156
+ var callback = _a[_i];
157
+ callback('', iCalExpander, xhr);
158
+ }
159
+ internalState.completed = true;
160
+ internalState.callbacks = [];
161
+ internalState.iCalExpander = iCalExpander;
162
+ internalState.xhr = xhr;
163
+ }, function (errorMessage, xhr) {
164
+ for (var _i = 0, _a = internalState.callbacks; _i < _a.length; _i++) {
165
+ var callback = _a[_i];
166
+ callback(errorMessage, null, xhr);
167
+ }
168
+ internalState.completed = true;
169
+ internalState.callbacks = [];
170
+ internalState.errorMessage = errorMessage;
171
+ internalState.xhr = xhr;
172
+ });
173
+ }
174
+ else if (!internalState.completed) {
175
+ internalState.callbacks.push(handleICalEvents);
176
+ }
177
+ else {
178
+ handleICalEvents(internalState.errorMessage, internalState.iCalExpander, internalState.xhr);
179
+ }
180
+ },
181
+ };
182
+ function requestICal(url, successCallback, failureCallback) {
183
+ var xhr = new XMLHttpRequest();
184
+ xhr.open('GET', url, true);
185
+ xhr.onload = function () {
186
+ if (xhr.status >= 200 && xhr.status < 400) {
187
+ successCallback(xhr.responseText, xhr);
188
+ }
189
+ else {
190
+ failureCallback('Request failed', xhr);
191
+ }
192
+ };
193
+ xhr.onerror = function () { return failureCallback('Request failed', xhr); };
194
+ xhr.send(null);
195
+ }
196
+ function expandICalEvents(iCalExpander, range) {
197
+ // expand the range. because our `range` is timeZone-agnostic UTC
198
+ // or maybe because ical.js always produces dates in local time? i forget
199
+ var rangeStart = addDays(range.start, -1);
200
+ var rangeEnd = addDays(range.end, 1);
201
+ var iCalRes = iCalExpander.between(rangeStart, rangeEnd); // end inclusive. will give extra results
202
+ var expanded = [];
203
+ // TODO: instead of using startDate/endDate.toString to communicate allDay,
204
+ // we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.
205
+ // single events
206
+ for (var _i = 0, _a = iCalRes.events; _i < _a.length; _i++) {
207
+ var iCalEvent = _a[_i];
208
+ expanded.push(__assign(__assign({}, buildNonDateProps(iCalEvent)), { start: iCalEvent.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)
209
+ ? iCalEvent.endDate.toString()
210
+ : null }));
211
+ }
212
+ // recurring event instances
213
+ for (var _b = 0, _c = iCalRes.occurrences; _b < _c.length; _b++) {
214
+ var iCalOccurence = _c[_b];
215
+ var iCalEvent = iCalOccurence.item;
216
+ expanded.push(__assign(__assign({}, buildNonDateProps(iCalEvent)), { start: iCalOccurence.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)
217
+ ? iCalOccurence.endDate.toString()
218
+ : null }));
219
+ }
220
+ return expanded;
221
+ }
222
+ function buildNonDateProps(iCalEvent) {
223
+ return {
224
+ title: iCalEvent.summary,
225
+ url: extractEventUrl(iCalEvent),
226
+ extendedProps: {
227
+ location: iCalEvent.location,
228
+ organizer: iCalEvent.organizer,
229
+ description: iCalEvent.description,
230
+ },
231
+ };
232
+ }
233
+ function extractEventUrl(iCalEvent) {
234
+ var urlProp = iCalEvent.component.getFirstProperty('url');
235
+ return urlProp ? urlProp.getFirstValue() : '';
236
+ }
237
+ function specifiesEnd(iCalEvent) {
238
+ return Boolean(iCalEvent.component.getFirstProperty('dtend')) ||
239
+ Boolean(iCalEvent.component.getFirstProperty('duration'));
240
+ }
241
+ var main = createPlugin({
242
+ eventSourceDefs: [eventSourceDef],
243
+ });
244
+
245
+ export default main;
246
+ //# sourceMappingURL=main.js.map
package/main.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sources":["src/ical-expander/IcalExpander.js","src/main.ts"],"sourcesContent":["/* eslint-disable */\n/*\nfrom https://github.com/mifi/ical-expander\nreleased under https://github.com/mifi/ical-expander/blob/master/LICENSE\noperates entirely in UTC\n*/\n\nimport * as ICAL from 'ical.js'\n\nexport class IcalExpander {\n constructor(opts) {\n this.maxIterations = opts.maxIterations != null ? opts.maxIterations : 1000;\n this.skipInvalidDates = opts.skipInvalidDates != null ? opts.skipInvalidDates : false;\n\n this.jCalData = ICAL.parse(opts.ics);\n this.component = new ICAL.Component(this.jCalData);\n this.events = this.component.getAllSubcomponents('vevent').map(vevent => new ICAL.Event(vevent));\n\n if (this.skipInvalidDates) {\n this.events = this.events.filter((evt) => {\n try {\n evt.startDate.toJSDate();\n evt.endDate.toJSDate();\n return true;\n } catch (err) {\n // skipping events with invalid time\n return false;\n }\n });\n }\n }\n\n between(after, before) {\n function isEventWithinRange(startTime, endTime) {\n return (!after || endTime >= after.getTime()) &&\n (!before || startTime <= before.getTime());\n }\n\n function getTimes(eventOrOccurrence) {\n const startTime = eventOrOccurrence.startDate.toJSDate().getTime();\n let endTime = eventOrOccurrence.endDate.toJSDate().getTime();\n\n // If it is an all day event, the end date is set to 00:00 of the next day\n // So we need to make it be 23:59:59 to compare correctly with the given range\n if (eventOrOccurrence.endDate.isDate && (endTime > startTime)) {\n endTime -= 1;\n }\n\n return { startTime, endTime };\n }\n\n const exceptions = [];\n\n this.events.forEach((event) => {\n if (event.isRecurrenceException()) exceptions.push(event);\n });\n\n const ret = {\n events: [],\n occurrences: [],\n };\n\n this.events.filter(e => !e.isRecurrenceException()).forEach((event) => {\n const exdates = [];\n\n event.component.getAllProperties('exdate').forEach((exdateProp) => {\n const exdate = exdateProp.getFirstValue();\n exdates.push(exdate.toJSDate().getTime());\n });\n\n // Recurring event is handled differently\n if (event.isRecurring()) {\n const iterator = event.iterator();\n\n let next;\n let i = 0;\n\n do {\n i += 1;\n next = iterator.next();\n if (next) {\n const occurrence = event.getOccurrenceDetails(next);\n\n const { startTime, endTime } = getTimes(occurrence);\n\n const isOccurrenceExcluded = exdates.indexOf(startTime) !== -1;\n\n // TODO check that within same day?\n const exception = exceptions.find(ex => ex.uid === event.uid && ex.recurrenceId.toJSDate().getTime() === occurrence.startDate.toJSDate().getTime());\n\n // We have passed the max date, stop\n if (before && startTime > before.getTime()) break;\n\n // Check that we are within our range\n if (isEventWithinRange(startTime, endTime)) {\n if (exception) {\n ret.events.push(exception);\n } else if (!isOccurrenceExcluded) {\n ret.occurrences.push(occurrence);\n }\n }\n }\n }\n while (next && (!this.maxIterations || i < this.maxIterations));\n\n return;\n }\n\n // Non-recurring event:\n const { startTime, endTime } = getTimes(event);\n\n if (isEventWithinRange(startTime, endTime)) ret.events.push(event);\n });\n\n return ret;\n }\n\n before(before) {\n return this.between(undefined, before);\n }\n\n after(after) {\n return this.between(after);\n }\n\n all() {\n return this.between();\n }\n}\n","import { createPlugin, EventSourceDef, EventInput, DateRange, addDays } from '@fullcalendar/common'\nimport * as ICAL from 'ical.js'\nimport { IcalExpander } from './ical-expander/IcalExpander'\n\ntype Success = (rawFeed: string, xhr: XMLHttpRequest) => void\ntype Failure = (error: string, xhr: XMLHttpRequest) => void\n\ninterface ICalFeedMeta {\n url: string\n format: 'ics', // for EventSourceApi\n internalState?: InternalState // HACK. TODO: use classes in future\n}\n\ninterface InternalState {\n completed: boolean\n callbacks: ((errorMessage: string, iCalExpander: IcalExpander, xhr: XMLHttpRequest) => void)[]\n errorMessage: string\n iCalExpander: IcalExpander\n xhr: XMLHttpRequest | null\n}\n\nlet eventSourceDef: EventSourceDef<ICalFeedMeta> = {\n\n parseMeta(refined) {\n if (refined.url && refined.format === 'ics') {\n return {\n url: refined.url,\n format: 'ics',\n }\n }\n return null\n },\n\n fetch(arg, onSuccess, onFailure) {\n let { meta } = arg.eventSource\n let { internalState } = meta\n\n function handleICalEvents(errorMessage, iCalExpander: IcalExpander, xhr) {\n if (errorMessage) {\n onFailure({ message: errorMessage, xhr })\n } else {\n onSuccess({ rawEvents: expandICalEvents(iCalExpander, arg.range), xhr })\n }\n }\n\n /*\n NOTE: isRefetch is a HACK. we would do the recurring-expanding in a separate plugin hook,\n but we couldn't leverage built-in allDay-guessing, among other things.\n */\n if (!internalState || arg.isRefetch) {\n internalState = meta.internalState = { // our ghetto Promise\n completed: false,\n callbacks: [handleICalEvents],\n errorMessage: '',\n iCalExpander: null,\n xhr: null,\n }\n\n requestICal(\n meta.url,\n (rawFeed, xhr) => {\n let iCalExpander = new IcalExpander({\n ics: rawFeed,\n skipInvalidDates: true,\n })\n\n for (let callback of internalState.callbacks) {\n callback('', iCalExpander, xhr)\n }\n\n internalState.completed = true\n internalState.callbacks = []\n internalState.iCalExpander = iCalExpander\n internalState.xhr = xhr\n },\n (errorMessage, xhr) => {\n for (let callback of internalState.callbacks) {\n callback(errorMessage, null, xhr)\n }\n\n internalState.completed = true\n internalState.callbacks = []\n internalState.errorMessage = errorMessage\n internalState.xhr = xhr\n },\n )\n } else if (!internalState.completed) {\n internalState.callbacks.push(handleICalEvents)\n } else {\n handleICalEvents(internalState.errorMessage, internalState.iCalExpander, internalState.xhr)\n }\n },\n}\n\nfunction requestICal(url: string, successCallback: Success, failureCallback: Failure) {\n const xhr = new XMLHttpRequest()\n xhr.open('GET', url, true)\n xhr.onload = () => {\n if (xhr.status >= 200 && xhr.status < 400) {\n successCallback(xhr.responseText, xhr)\n } else {\n failureCallback('Request failed', xhr)\n }\n }\n xhr.onerror = () => failureCallback('Request failed', xhr)\n xhr.send(null)\n}\n\nfunction expandICalEvents(iCalExpander: IcalExpander, range: DateRange): EventInput[] {\n // expand the range. because our `range` is timeZone-agnostic UTC\n // or maybe because ical.js always produces dates in local time? i forget\n let rangeStart = addDays(range.start, -1)\n let rangeEnd = addDays(range.end, 1)\n\n let iCalRes = iCalExpander.between(rangeStart, rangeEnd) // end inclusive. will give extra results\n let expanded: EventInput[] = []\n\n // TODO: instead of using startDate/endDate.toString to communicate allDay,\n // we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.\n\n // single events\n for (let iCalEvent of iCalRes.events) {\n expanded.push({\n ...buildNonDateProps(iCalEvent),\n start: iCalEvent.startDate.toString(),\n end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)\n ? iCalEvent.endDate.toString()\n : null,\n })\n }\n\n // recurring event instances\n for (let iCalOccurence of iCalRes.occurrences) {\n let iCalEvent = iCalOccurence.item\n expanded.push({\n ...buildNonDateProps(iCalEvent),\n start: iCalOccurence.startDate.toString(),\n end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)\n ? iCalOccurence.endDate.toString()\n : null,\n })\n }\n\n return expanded\n}\n\nfunction buildNonDateProps(iCalEvent: ICAL.Event): EventInput {\n return {\n title: iCalEvent.summary,\n url: extractEventUrl(iCalEvent),\n extendedProps: {\n location: iCalEvent.location,\n organizer: iCalEvent.organizer,\n description: iCalEvent.description,\n },\n }\n}\n\nfunction extractEventUrl(iCalEvent: ICAL.Event): string {\n let urlProp = iCalEvent.component.getFirstProperty('url')\n return urlProp ? urlProp.getFirstValue() : ''\n}\n\nfunction specifiesEnd(iCalEvent: ICAL.Event) {\n return Boolean(iCalEvent.component.getFirstProperty('dtend')) ||\n Boolean(iCalEvent.component.getFirstProperty('duration'))\n}\n\nexport default createPlugin({\n eventSourceDefs: [eventSourceDef],\n})\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@fullcalendar/icalendar",
3
+ "version": "5.10.0",
4
+ "title": "FullCalendar iCalendar Plugin",
5
+ "description": "Fetch events from a public iCalendar / .ics feed",
6
+ "docs": "https://fullcalendar.io/docs/icalendar",
7
+ "dependencies": {
8
+ "@fullcalendar/common": "~5.10.0",
9
+ "ical.js": "^1.4.0",
10
+ "tslib": "^2.1.0"
11
+ },
12
+ "main": "main.cjs.js",
13
+ "module": "main.js",
14
+ "types": "main.d.ts",
15
+ "jsdelivr": "main.global.min.js",
16
+ "browserGlobal": "FullCalendarICalendar",
17
+ "homepage": "https://fullcalendar.io/",
18
+ "bugs": "https://fullcalendar.io/reporting-bugs",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/fullcalendar/fullcalendar.git",
22
+ "homepage": "https://github.com/fullcalendar/fullcalendar"
23
+ },
24
+ "license": "MIT",
25
+ "author": {
26
+ "name": "NJ Pearman",
27
+ "email": "n.pearman@gmail.com",
28
+ "url": "https://github.com/njpearman/"
29
+ }
30
+ }