@fullcalendar/icalendar 7.0.0-rc.0 → 7.1.0-alpha.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.md +1 -1
- package/README.md +10 -4
- package/{index.global.js → global.js} +51 -23
- package/index.d.ts +56 -2
- package/index.js +18 -10
- package/package.json +13 -13
- package/index.cjs +0 -201
- package/index.global.min.js +0 -6
package/LICENSE.md
CHANGED
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npm install ical.js
|
|
|
14
14
|
Then, install the FullCalendar core package, the iCalendar plugin, and any other plugins (like [daygrid](https://fullcalendar.io/docs/month-view)):
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
|
-
npm install
|
|
17
|
+
npm install fullcalendar @fullcalendar/icalendar temporal-polyfill
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
## Usage
|
|
@@ -22,15 +22,21 @@ npm install @fullcalendar/core @fullcalendar/icalendar @fullcalendar/daygrid
|
|
|
22
22
|
Instantiate a Calendar with the necessary plugins and options:
|
|
23
23
|
|
|
24
24
|
```js
|
|
25
|
-
import { Calendar } from '
|
|
25
|
+
import { Calendar } from 'fullcalendar'
|
|
26
|
+
import classicThemePlugin from 'fullcalendar/themes/classic'
|
|
27
|
+
import dayGridPlugin from 'fullcalendar/daygrid'
|
|
26
28
|
import iCalendarPlugin from '@fullcalendar/icalendar'
|
|
27
|
-
|
|
29
|
+
|
|
30
|
+
import 'fullcalendar/skeleton.css'
|
|
31
|
+
import 'fullcalendar/themes/classic/theme.css'
|
|
32
|
+
import 'fullcalendar/themes/classic/palette.css'
|
|
28
33
|
|
|
29
34
|
const calendarEl = document.getElementById('calendar')
|
|
30
35
|
const calendar = new Calendar(calendarEl, {
|
|
31
36
|
plugins: [
|
|
32
37
|
iCalendarPlugin,
|
|
33
|
-
dayGridPlugin
|
|
38
|
+
dayGridPlugin,
|
|
39
|
+
classicThemePlugin
|
|
34
40
|
],
|
|
35
41
|
initialView: 'dayGridMonth',
|
|
36
42
|
events: {
|
|
@@ -1,14 +1,39 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
FullCalendar iCalendar Plugin v7.
|
|
2
|
+
FullCalendar iCalendar Plugin v7.1.0-alpha.0
|
|
3
3
|
Docs & License: https://fullcalendar.io/docs/icalendar
|
|
4
|
-
(c)
|
|
4
|
+
(c) 2025 Adam Shaw
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
(function (ICAL) {
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
function
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
10
|
|
|
11
|
-
var ICAL__default = /*#__PURE__*/
|
|
11
|
+
var ICAL__default = /*#__PURE__*/_interopDefaultLegacy(ICAL);
|
|
12
|
+
|
|
13
|
+
function addDays(m, n) {
|
|
14
|
+
let a = dateToUtcArray(m);
|
|
15
|
+
a[2] += n;
|
|
16
|
+
return arrayToUtcDate(a);
|
|
17
|
+
}
|
|
18
|
+
function dateToUtcArray(date) {
|
|
19
|
+
return [
|
|
20
|
+
date.getUTCFullYear(),
|
|
21
|
+
date.getUTCMonth(),
|
|
22
|
+
date.getUTCDate(),
|
|
23
|
+
date.getUTCHours(),
|
|
24
|
+
date.getUTCMinutes(),
|
|
25
|
+
date.getUTCSeconds(),
|
|
26
|
+
date.getUTCMilliseconds(),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
function arrayToUtcDate(a) {
|
|
30
|
+
// according to web standards (and Safari), a month index is required.
|
|
31
|
+
// massage if only given a year.
|
|
32
|
+
if (a.length === 1) {
|
|
33
|
+
a = a.concat([0]);
|
|
34
|
+
}
|
|
35
|
+
return new Date(Date.UTC(...a));
|
|
36
|
+
}
|
|
12
37
|
|
|
13
38
|
/* eslint-disable */
|
|
14
39
|
class IcalExpander {
|
|
@@ -120,7 +145,8 @@ FullCalendar.ICalendar = (function (exports, core, internal, ICAL) {
|
|
|
120
145
|
}
|
|
121
146
|
return null;
|
|
122
147
|
},
|
|
123
|
-
fetch(arg, successCallback,
|
|
148
|
+
fetch(arg, successCallback, // any
|
|
149
|
+
errorCallback) {
|
|
124
150
|
let meta = arg.eventSource.meta;
|
|
125
151
|
let { internalState } = meta;
|
|
126
152
|
/*
|
|
@@ -152,24 +178,32 @@ FullCalendar.ICalendar = (function (exports, core, internal, ICAL) {
|
|
|
152
178
|
function expandICalEvents(iCalExpander, range) {
|
|
153
179
|
// expand the range. because our `range` is timeZone-agnostic UTC
|
|
154
180
|
// or maybe because ical.js always produces dates in local time? i forget
|
|
155
|
-
let rangeStart =
|
|
156
|
-
let rangeEnd =
|
|
181
|
+
let rangeStart = addDays(range.start, -1);
|
|
182
|
+
let rangeEnd = addDays(range.end, 1);
|
|
157
183
|
let iCalRes = iCalExpander.between(rangeStart, rangeEnd); // end inclusive. will give extra results
|
|
158
184
|
let expanded = [];
|
|
159
185
|
// TODO: instead of using startDate/endDate.toString to communicate allDay,
|
|
160
186
|
// we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.
|
|
161
187
|
// single events
|
|
162
188
|
for (let iCalEvent of iCalRes.events) {
|
|
163
|
-
expanded.push(
|
|
189
|
+
expanded.push({
|
|
190
|
+
...buildNonDateProps(iCalEvent),
|
|
191
|
+
start: iCalEvent.startDate.toString(),
|
|
192
|
+
end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)
|
|
164
193
|
? iCalEvent.endDate.toString()
|
|
165
|
-
: null
|
|
194
|
+
: null,
|
|
195
|
+
});
|
|
166
196
|
}
|
|
167
197
|
// recurring event instances
|
|
168
198
|
for (let iCalOccurence of iCalRes.occurrences) {
|
|
169
199
|
let iCalEvent = iCalOccurence.item;
|
|
170
|
-
expanded.push(
|
|
200
|
+
expanded.push({
|
|
201
|
+
...buildNonDateProps(iCalEvent),
|
|
202
|
+
start: iCalOccurence.startDate.toString(),
|
|
203
|
+
end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)
|
|
171
204
|
? iCalOccurence.endDate.toString()
|
|
172
|
-
: null
|
|
205
|
+
: null,
|
|
206
|
+
});
|
|
173
207
|
}
|
|
174
208
|
return expanded;
|
|
175
209
|
}
|
|
@@ -193,17 +227,11 @@ FullCalendar.ICalendar = (function (exports, core, internal, ICAL) {
|
|
|
193
227
|
Boolean(iCalEvent.component.getFirstProperty('duration'));
|
|
194
228
|
}
|
|
195
229
|
|
|
196
|
-
var plugin =
|
|
197
|
-
name: '
|
|
230
|
+
var plugin = {
|
|
231
|
+
name: 'icalendar',
|
|
198
232
|
eventSourceDefs: [eventSourceDef],
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
core.globalPlugins.push(plugin);
|
|
202
|
-
|
|
203
|
-
exports["default"] = plugin;
|
|
204
|
-
|
|
205
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
233
|
+
};
|
|
206
234
|
|
|
207
|
-
|
|
235
|
+
FullCalendar.globalPlugins.push(plugin);
|
|
208
236
|
|
|
209
|
-
})(
|
|
237
|
+
})(ICAL);
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,60 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ICAL from 'ical.js';
|
|
2
|
+
import * as _full_ui_headless_calendar from '@full-ui/headless-calendar';
|
|
2
3
|
|
|
3
|
-
declare
|
|
4
|
+
declare class IcalExpander {
|
|
5
|
+
constructor(opts: any);
|
|
6
|
+
maxIterations: any;
|
|
7
|
+
skipInvalidDates: any;
|
|
8
|
+
jCalData: any;
|
|
9
|
+
component: ICAL.Component;
|
|
10
|
+
events: ICAL.Event[];
|
|
11
|
+
between(after: any, before: any): {
|
|
12
|
+
events: any[];
|
|
13
|
+
occurrences: any[];
|
|
14
|
+
};
|
|
15
|
+
before(before: any): {
|
|
16
|
+
events: any[];
|
|
17
|
+
occurrences: any[];
|
|
18
|
+
};
|
|
19
|
+
after(after: any): {
|
|
20
|
+
events: any[];
|
|
21
|
+
occurrences: any[];
|
|
22
|
+
};
|
|
23
|
+
all(): {
|
|
24
|
+
events: any[];
|
|
25
|
+
occurrences: any[];
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ICalFeedMeta {
|
|
30
|
+
url: string;
|
|
31
|
+
format: 'ics';
|
|
32
|
+
internalState?: InternalState;
|
|
33
|
+
}
|
|
34
|
+
interface InternalState {
|
|
35
|
+
iCalExpanderPromise: Promise<IcalExpander>;
|
|
36
|
+
response: Response | null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare const _default: {
|
|
40
|
+
name: string;
|
|
41
|
+
eventSourceDefs: {
|
|
42
|
+
parseMeta(refined: {
|
|
43
|
+
url: string;
|
|
44
|
+
format: string;
|
|
45
|
+
}): {
|
|
46
|
+
url: string;
|
|
47
|
+
format: string;
|
|
48
|
+
};
|
|
49
|
+
fetch(arg: {
|
|
50
|
+
isRefetch: boolean;
|
|
51
|
+
range: _full_ui_headless_calendar.DateRange;
|
|
52
|
+
eventSource: {
|
|
53
|
+
meta: ICalFeedMeta;
|
|
54
|
+
};
|
|
55
|
+
}, successCallback: any, errorCallback: any): void;
|
|
56
|
+
}[];
|
|
57
|
+
};
|
|
4
58
|
//# sourceMappingURL=index.d.ts.map
|
|
5
59
|
|
|
6
60
|
export { _default as default };
|
package/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { addDays } from '@fullcalendar/core/internal.js';
|
|
1
|
+
import { addDays } from '@full-ui/headless-calendar';
|
|
3
2
|
import ICAL from 'ical.js';
|
|
4
3
|
|
|
5
4
|
/* eslint-disable */
|
|
@@ -112,7 +111,8 @@ const eventSourceDef = {
|
|
|
112
111
|
}
|
|
113
112
|
return null;
|
|
114
113
|
},
|
|
115
|
-
fetch(arg, successCallback,
|
|
114
|
+
fetch(arg, successCallback, // any
|
|
115
|
+
errorCallback) {
|
|
116
116
|
let meta = arg.eventSource.meta;
|
|
117
117
|
let { internalState } = meta;
|
|
118
118
|
/*
|
|
@@ -152,16 +152,24 @@ function expandICalEvents(iCalExpander, range) {
|
|
|
152
152
|
// we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.
|
|
153
153
|
// single events
|
|
154
154
|
for (let iCalEvent of iCalRes.events) {
|
|
155
|
-
expanded.push(
|
|
155
|
+
expanded.push({
|
|
156
|
+
...buildNonDateProps(iCalEvent),
|
|
157
|
+
start: iCalEvent.startDate.toString(),
|
|
158
|
+
end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)
|
|
156
159
|
? iCalEvent.endDate.toString()
|
|
157
|
-
: null
|
|
160
|
+
: null,
|
|
161
|
+
});
|
|
158
162
|
}
|
|
159
163
|
// recurring event instances
|
|
160
164
|
for (let iCalOccurence of iCalRes.occurrences) {
|
|
161
165
|
let iCalEvent = iCalOccurence.item;
|
|
162
|
-
expanded.push(
|
|
166
|
+
expanded.push({
|
|
167
|
+
...buildNonDateProps(iCalEvent),
|
|
168
|
+
start: iCalOccurence.startDate.toString(),
|
|
169
|
+
end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)
|
|
163
170
|
? iCalOccurence.endDate.toString()
|
|
164
|
-
: null
|
|
171
|
+
: null,
|
|
172
|
+
});
|
|
165
173
|
}
|
|
166
174
|
return expanded;
|
|
167
175
|
}
|
|
@@ -185,9 +193,9 @@ function specifiesEnd(iCalEvent) {
|
|
|
185
193
|
Boolean(iCalEvent.component.getFirstProperty('duration'));
|
|
186
194
|
}
|
|
187
195
|
|
|
188
|
-
var index =
|
|
189
|
-
name: '
|
|
196
|
+
var index = {
|
|
197
|
+
name: 'icalendar',
|
|
190
198
|
eventSourceDefs: [eventSourceDef],
|
|
191
|
-
}
|
|
199
|
+
};
|
|
192
200
|
|
|
193
201
|
export { index as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fullcalendar/icalendar",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.0-alpha.0",
|
|
4
4
|
"title": "FullCalendar iCalendar Plugin",
|
|
5
5
|
"description": "Display events from a public iCalendar feed",
|
|
6
6
|
"keywords": [
|
|
@@ -12,9 +12,13 @@
|
|
|
12
12
|
"ics"
|
|
13
13
|
],
|
|
14
14
|
"homepage": "https://fullcalendar.io/docs/icalendar",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@full-ui/headless-calendar": "7.1.0-alpha.0",
|
|
17
|
+
"@fullcalendar/core": "7.1.0-alpha.0"
|
|
18
|
+
},
|
|
15
19
|
"peerDependencies": {
|
|
16
|
-
"
|
|
17
|
-
"
|
|
20
|
+
"ical.js": "^2.0.0",
|
|
21
|
+
"temporal-polyfill": "^0.3.2"
|
|
18
22
|
},
|
|
19
23
|
"type": "module",
|
|
20
24
|
"bugs": "https://fullcalendar.io/reporting-bugs",
|
|
@@ -29,21 +33,17 @@
|
|
|
29
33
|
"email": "arshaw@arshaw.com",
|
|
30
34
|
"url": "http://arshaw.com/"
|
|
31
35
|
},
|
|
32
|
-
"copyright": "
|
|
36
|
+
"copyright": "2025 Adam Shaw",
|
|
33
37
|
"types": "./index.d.ts",
|
|
34
|
-
"main": "./index.
|
|
35
|
-
"module": "./index.js",
|
|
36
|
-
"unpkg": "./index.global.min.js",
|
|
37
|
-
"jsdelivr": "./index.global.min.js",
|
|
38
|
+
"main": "./index.js",
|
|
38
39
|
"exports": {
|
|
39
40
|
"./package.json": "./package.json",
|
|
40
|
-
"./index.cjs": "./index.cjs",
|
|
41
|
-
"./index.js": "./index.js",
|
|
42
41
|
".": {
|
|
43
42
|
"types": "./index.d.ts",
|
|
44
|
-
"
|
|
45
|
-
"import": "./index.js"
|
|
43
|
+
"default": "./index.js"
|
|
46
44
|
}
|
|
47
45
|
},
|
|
48
|
-
"sideEffects":
|
|
46
|
+
"sideEffects": [
|
|
47
|
+
"./global.js"
|
|
48
|
+
]
|
|
49
49
|
}
|
package/index.cjs
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var index_cjs = require('@fullcalendar/core/index.cjs');
|
|
6
|
-
var internal_cjs = require('@fullcalendar/core/internal.cjs');
|
|
7
|
-
var ICAL = require('ical.js');
|
|
8
|
-
|
|
9
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
-
|
|
11
|
-
var ICAL__default = /*#__PURE__*/_interopDefaultLegacy(ICAL);
|
|
12
|
-
|
|
13
|
-
/* eslint-disable */
|
|
14
|
-
class IcalExpander {
|
|
15
|
-
constructor(opts) {
|
|
16
|
-
this.maxIterations = opts.maxIterations != null ? opts.maxIterations : 1000;
|
|
17
|
-
this.skipInvalidDates = opts.skipInvalidDates != null ? opts.skipInvalidDates : false;
|
|
18
|
-
this.jCalData = ICAL__default["default"].parse(opts.ics);
|
|
19
|
-
this.component = new ICAL__default["default"].Component(this.jCalData);
|
|
20
|
-
this.events = this.component.getAllSubcomponents('vevent').map(vevent => new ICAL__default["default"].Event(vevent));
|
|
21
|
-
if (this.skipInvalidDates) {
|
|
22
|
-
this.events = this.events.filter((evt) => {
|
|
23
|
-
try {
|
|
24
|
-
evt.startDate.toJSDate();
|
|
25
|
-
evt.endDate.toJSDate();
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
// skipping events with invalid time
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
between(after, before) {
|
|
36
|
-
function isEventWithinRange(startTime, endTime) {
|
|
37
|
-
return (!after || endTime >= after.getTime()) &&
|
|
38
|
-
(!before || startTime <= before.getTime());
|
|
39
|
-
}
|
|
40
|
-
function getTimes(eventOrOccurrence) {
|
|
41
|
-
const startTime = eventOrOccurrence.startDate.toJSDate().getTime();
|
|
42
|
-
let endTime = eventOrOccurrence.endDate.toJSDate().getTime();
|
|
43
|
-
// If it is an all day event, the end date is set to 00:00 of the next day
|
|
44
|
-
// So we need to make it be 23:59:59 to compare correctly with the given range
|
|
45
|
-
if (eventOrOccurrence.endDate.isDate && (endTime > startTime)) {
|
|
46
|
-
endTime -= 1;
|
|
47
|
-
}
|
|
48
|
-
return { startTime, endTime };
|
|
49
|
-
}
|
|
50
|
-
const exceptions = [];
|
|
51
|
-
this.events.forEach((event) => {
|
|
52
|
-
if (event.isRecurrenceException())
|
|
53
|
-
exceptions.push(event);
|
|
54
|
-
});
|
|
55
|
-
const ret = {
|
|
56
|
-
events: [],
|
|
57
|
-
occurrences: [],
|
|
58
|
-
};
|
|
59
|
-
this.events.filter(e => !e.isRecurrenceException()).forEach((event) => {
|
|
60
|
-
const exdates = [];
|
|
61
|
-
event.component.getAllProperties('exdate').forEach((exdateProp) => {
|
|
62
|
-
const exdate = exdateProp.getFirstValue();
|
|
63
|
-
exdates.push(exdate.toJSDate().getTime());
|
|
64
|
-
});
|
|
65
|
-
// Recurring event is handled differently
|
|
66
|
-
if (event.isRecurring()) {
|
|
67
|
-
const iterator = event.iterator();
|
|
68
|
-
let next;
|
|
69
|
-
let i = 0;
|
|
70
|
-
do {
|
|
71
|
-
i += 1;
|
|
72
|
-
next = iterator.next();
|
|
73
|
-
if (next) {
|
|
74
|
-
const occurrence = event.getOccurrenceDetails(next);
|
|
75
|
-
const { startTime, endTime } = getTimes(occurrence);
|
|
76
|
-
const isOccurrenceExcluded = exdates.indexOf(startTime) !== -1;
|
|
77
|
-
// TODO check that within same day?
|
|
78
|
-
const exception = exceptions.find(ex => ex.uid === event.uid && ex.recurrenceId.toJSDate().getTime() === occurrence.startDate.toJSDate().getTime());
|
|
79
|
-
// We have passed the max date, stop
|
|
80
|
-
if (before && startTime > before.getTime())
|
|
81
|
-
break;
|
|
82
|
-
// Check that we are within our range
|
|
83
|
-
if (isEventWithinRange(startTime, endTime)) {
|
|
84
|
-
if (exception) {
|
|
85
|
-
ret.events.push(exception);
|
|
86
|
-
}
|
|
87
|
-
else if (!isOccurrenceExcluded) {
|
|
88
|
-
ret.occurrences.push(occurrence);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
} while (next && (!this.maxIterations || i < this.maxIterations));
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
// Non-recurring event:
|
|
96
|
-
const { startTime, endTime } = getTimes(event);
|
|
97
|
-
if (isEventWithinRange(startTime, endTime))
|
|
98
|
-
ret.events.push(event);
|
|
99
|
-
});
|
|
100
|
-
return ret;
|
|
101
|
-
}
|
|
102
|
-
before(before) {
|
|
103
|
-
return this.between(undefined, before);
|
|
104
|
-
}
|
|
105
|
-
after(after) {
|
|
106
|
-
return this.between(after);
|
|
107
|
-
}
|
|
108
|
-
all() {
|
|
109
|
-
return this.between();
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const eventSourceDef = {
|
|
114
|
-
parseMeta(refined) {
|
|
115
|
-
if (refined.url && refined.format === 'ics') {
|
|
116
|
-
return {
|
|
117
|
-
url: refined.url,
|
|
118
|
-
format: 'ics',
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
return null;
|
|
122
|
-
},
|
|
123
|
-
fetch(arg, successCallback, errorCallback) {
|
|
124
|
-
let meta = arg.eventSource.meta;
|
|
125
|
-
let { internalState } = meta;
|
|
126
|
-
/*
|
|
127
|
-
NOTE: isRefetch is a HACK. we would do the recurring-expanding in a separate plugin hook,
|
|
128
|
-
but we couldn't leverage built-in allDay-guessing, among other things.
|
|
129
|
-
*/
|
|
130
|
-
if (!internalState || arg.isRefetch) {
|
|
131
|
-
internalState = meta.internalState = {
|
|
132
|
-
response: null,
|
|
133
|
-
iCalExpanderPromise: fetch(meta.url, { method: 'GET' }).then((response) => {
|
|
134
|
-
return response.text().then((icsText) => {
|
|
135
|
-
internalState.response = response;
|
|
136
|
-
return new IcalExpander({
|
|
137
|
-
ics: icsText,
|
|
138
|
-
skipInvalidDates: true,
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
}),
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
internalState.iCalExpanderPromise.then((iCalExpander) => {
|
|
145
|
-
successCallback({
|
|
146
|
-
rawEvents: expandICalEvents(iCalExpander, arg.range),
|
|
147
|
-
response: internalState.response,
|
|
148
|
-
});
|
|
149
|
-
}, errorCallback);
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
function expandICalEvents(iCalExpander, range) {
|
|
153
|
-
// expand the range. because our `range` is timeZone-agnostic UTC
|
|
154
|
-
// or maybe because ical.js always produces dates in local time? i forget
|
|
155
|
-
let rangeStart = internal_cjs.addDays(range.start, -1);
|
|
156
|
-
let rangeEnd = internal_cjs.addDays(range.end, 1);
|
|
157
|
-
let iCalRes = iCalExpander.between(rangeStart, rangeEnd); // end inclusive. will give extra results
|
|
158
|
-
let expanded = [];
|
|
159
|
-
// TODO: instead of using startDate/endDate.toString to communicate allDay,
|
|
160
|
-
// we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.
|
|
161
|
-
// single events
|
|
162
|
-
for (let iCalEvent of iCalRes.events) {
|
|
163
|
-
expanded.push(Object.assign(Object.assign({}, buildNonDateProps(iCalEvent)), { start: iCalEvent.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)
|
|
164
|
-
? iCalEvent.endDate.toString()
|
|
165
|
-
: null }));
|
|
166
|
-
}
|
|
167
|
-
// recurring event instances
|
|
168
|
-
for (let iCalOccurence of iCalRes.occurrences) {
|
|
169
|
-
let iCalEvent = iCalOccurence.item;
|
|
170
|
-
expanded.push(Object.assign(Object.assign({}, buildNonDateProps(iCalEvent)), { start: iCalOccurence.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)
|
|
171
|
-
? iCalOccurence.endDate.toString()
|
|
172
|
-
: null }));
|
|
173
|
-
}
|
|
174
|
-
return expanded;
|
|
175
|
-
}
|
|
176
|
-
function buildNonDateProps(iCalEvent) {
|
|
177
|
-
return {
|
|
178
|
-
title: iCalEvent.summary,
|
|
179
|
-
url: extractEventUrl(iCalEvent),
|
|
180
|
-
extendedProps: {
|
|
181
|
-
location: iCalEvent.location,
|
|
182
|
-
organizer: iCalEvent.organizer,
|
|
183
|
-
description: iCalEvent.description,
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
function extractEventUrl(iCalEvent) {
|
|
188
|
-
let urlProp = iCalEvent.component.getFirstProperty('url');
|
|
189
|
-
return urlProp ? urlProp.getFirstValue() : '';
|
|
190
|
-
}
|
|
191
|
-
function specifiesEnd(iCalEvent) {
|
|
192
|
-
return Boolean(iCalEvent.component.getFirstProperty('dtend')) ||
|
|
193
|
-
Boolean(iCalEvent.component.getFirstProperty('duration'));
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
var index = index_cjs.createPlugin({
|
|
197
|
-
name: '@fullcalendar/icalendar',
|
|
198
|
-
eventSourceDefs: [eventSourceDef],
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
exports["default"] = index;
|
package/index.global.min.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
FullCalendar iCalendar Plugin v7.0.0-rc.0
|
|
3
|
-
Docs & License: https://fullcalendar.io/docs/icalendar
|
|
4
|
-
(c) 2024 Adam Shaw
|
|
5
|
-
*/
|
|
6
|
-
FullCalendar.ICalendar=function(e,t,n,r){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}var s=a(r);class i{constructor(e){this.maxIterations=null!=e.maxIterations?e.maxIterations:1e3,this.skipInvalidDates=null!=e.skipInvalidDates&&e.skipInvalidDates,this.jCalData=s.default.parse(e.ics),this.component=new s.default.Component(this.jCalData),this.events=this.component.getAllSubcomponents("vevent").map(e=>new s.default.Event(e)),this.skipInvalidDates&&(this.events=this.events.filter(e=>{try{return e.startDate.toJSDate(),e.endDate.toJSDate(),!0}catch(e){return!1}}))}between(e,t){function n(n,r){return(!e||r>=e.getTime())&&(!t||n<=t.getTime())}function r(e){const t=e.startDate.toJSDate().getTime();let n=e.endDate.toJSDate().getTime();return e.endDate.isDate&&n>t&&(n-=1),{startTime:t,endTime:n}}const a=[];this.events.forEach(e=>{e.isRecurrenceException()&&a.push(e)});const s={events:[],occurrences:[]};return this.events.filter(e=>!e.isRecurrenceException()).forEach(e=>{const i=[];if(e.component.getAllProperties("exdate").forEach(e=>{const t=e.getFirstValue();i.push(t.toJSDate().getTime())}),e.isRecurring()){const o=e.iterator();let l,u=0;do{if(u+=1,l=o.next(),l){const o=e.getOccurrenceDetails(l),{startTime:u,endTime:c}=r(o),d=-1!==i.indexOf(u),p=a.find(t=>t.uid===e.uid&&t.recurrenceId.toJSDate().getTime()===o.startDate.toJSDate().getTime());if(t&&u>t.getTime())break;n(u,c)&&(p?s.events.push(p):d||s.occurrences.push(o))}}while(l&&(!this.maxIterations||u<this.maxIterations));return}const{startTime:o,endTime:l}=r(e);n(o,l)&&s.events.push(e)}),s}before(e){return this.between(void 0,e)}after(e){return this.between(e)}all(){return this.between()}}const o={parseMeta:e=>e.url&&"ics"===e.format?{url:e.url,format:"ics"}:null,fetch(e,t,n){let r=e.eventSource.meta,{internalState:a}=r;a&&!e.isRefetch||(a=r.internalState={response:null,iCalExpanderPromise:fetch(r.url,{method:"GET"}).then(e=>e.text().then(t=>(a.response=e,new i({ics:t,skipInvalidDates:!0}))))}),a.iCalExpanderPromise.then(n=>{t({rawEvents:l(n,e.range),response:a.response})},n)}};function l(e,t){let r=n.addDays(t.start,-1),a=n.addDays(t.end,1),s=e.between(r,a),i=[];for(let e of s.events)i.push(Object.assign(Object.assign({},u(e)),{start:e.startDate.toString(),end:d(e)&&e.endDate?e.endDate.toString():null}));for(let e of s.occurrences){let t=e.item;i.push(Object.assign(Object.assign({},u(t)),{start:e.startDate.toString(),end:d(t)&&e.endDate?e.endDate.toString():null}))}return i}function u(e){return{title:e.summary,url:c(e),extendedProps:{location:e.location,organizer:e.organizer,description:e.description}}}function c(e){let t=e.component.getFirstProperty("url");return t?t.getFirstValue():""}function d(e){return Boolean(e.component.getFirstProperty("dtend"))||Boolean(e.component.getFirstProperty("duration"))}var p=t.createPlugin({name:"@fullcalendar/icalendar",eventSourceDefs:[o]});return t.globalPlugins.push(p),e.default=p,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal,ICAL);
|