ical-generator 3.5.2-develop.1 → 3.5.2-develop.2
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/package.json +10 -9
- package/src/alarm.ts +623 -0
- package/src/attendee.ts +614 -0
- package/src/calendar.ts +864 -0
- package/src/category.ts +98 -0
- package/src/event.ts +1669 -0
- package/src/index.ts +118 -0
- package/src/tools.ts +402 -0
- package/src/types.ts +111 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ical-generator entrypoint
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
import ICalCalendar, {ICalCalendarData} from './calendar';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a new, empty calendar and returns it.
|
|
12
|
+
*
|
|
13
|
+
* ```javascript
|
|
14
|
+
* import ical from 'ical-generator';
|
|
15
|
+
*
|
|
16
|
+
* // or use require:
|
|
17
|
+
* // const ical = require('ical-generator');
|
|
18
|
+
*
|
|
19
|
+
* const cal = ical();
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* You can pass options to setup your calendar or use setters to do this.
|
|
23
|
+
*
|
|
24
|
+
* ```javascript
|
|
25
|
+
* import ical from 'ical-generator';
|
|
26
|
+
*
|
|
27
|
+
* // or use require:
|
|
28
|
+
* // const ical = require('ical-generator');
|
|
29
|
+
* const cal = ical({domain: 'sebbo.net'});
|
|
30
|
+
*
|
|
31
|
+
* // is the same as
|
|
32
|
+
*
|
|
33
|
+
* const cal = ical().domain('sebbo.net');
|
|
34
|
+
*
|
|
35
|
+
* // is the same as
|
|
36
|
+
*
|
|
37
|
+
* const cal = ical();
|
|
38
|
+
* cal.domain('sebbo.net');
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @param data Calendar data
|
|
42
|
+
*/
|
|
43
|
+
function ical(data?: ICalCalendarData): ICalCalendar {
|
|
44
|
+
return new ICalCalendar(data);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default ical;
|
|
48
|
+
|
|
49
|
+
export {
|
|
50
|
+
default as ICalAlarm,
|
|
51
|
+
ICalAlarmData,
|
|
52
|
+
ICalAlarmType,
|
|
53
|
+
ICalAlarmTypeValue,
|
|
54
|
+
ICalAlarmJSONData,
|
|
55
|
+
ICalAttachment
|
|
56
|
+
} from './alarm';
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
default as ICalAttendee,
|
|
60
|
+
ICalAttendeeData,
|
|
61
|
+
ICalAttendeeType,
|
|
62
|
+
ICalAttendeeRole,
|
|
63
|
+
ICalAttendeeStatus,
|
|
64
|
+
ICalAttendeeJSONData
|
|
65
|
+
} from './attendee';
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
default as ICalCalendar,
|
|
69
|
+
ICalCalendarData,
|
|
70
|
+
ICalCalendarProdIdData,
|
|
71
|
+
ICalCalendarMethod,
|
|
72
|
+
ICalCalendarJSONData
|
|
73
|
+
} from './calendar';
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
default as ICalCategory,
|
|
77
|
+
ICalCategoryData
|
|
78
|
+
} from './category';
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
default as ICalEvent,
|
|
82
|
+
ICalEventStatus,
|
|
83
|
+
ICalEventBusyStatus,
|
|
84
|
+
ICalEventTransparency,
|
|
85
|
+
ICalEventData,
|
|
86
|
+
ICalEventJSONData,
|
|
87
|
+
ICalEventClass,
|
|
88
|
+
} from './event';
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
ICalDateTimeValue,
|
|
92
|
+
ICalRepeatingOptions,
|
|
93
|
+
ICalLocation,
|
|
94
|
+
ICalGeo,
|
|
95
|
+
ICalOrganizer,
|
|
96
|
+
ICalDescription,
|
|
97
|
+
ICalEventRepeatingFreq,
|
|
98
|
+
ICalWeekday,
|
|
99
|
+
ICalTimezone,
|
|
100
|
+
ICalMomentStub,
|
|
101
|
+
ICalMomentTimezoneStub,
|
|
102
|
+
ICalMomentDurationStub,
|
|
103
|
+
ICalLuxonDateTimeStub,
|
|
104
|
+
ICalDayJsStub,
|
|
105
|
+
ICalRRuleStub
|
|
106
|
+
} from './types';
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
formatDate,
|
|
110
|
+
formatDateTZ,
|
|
111
|
+
escape,
|
|
112
|
+
foldLines
|
|
113
|
+
} from './tools';
|
|
114
|
+
|
|
115
|
+
/* istanbul ignore else */
|
|
116
|
+
if (typeof module !== 'undefined') {
|
|
117
|
+
module.exports = Object.assign(ical, module.exports);
|
|
118
|
+
}
|
package/src/tools.ts
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ICalDateTimeValue, ICalDayJsStub, ICalLuxonDateTimeStub,
|
|
5
|
+
ICalMomentDurationStub,
|
|
6
|
+
ICalMomentStub,
|
|
7
|
+
ICalMomentTimezoneStub,
|
|
8
|
+
ICalOrganizer, ICalRRuleStub
|
|
9
|
+
} from './types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Converts a valid date/time object supported by this library to a string.
|
|
13
|
+
*/
|
|
14
|
+
export function formatDate (timezone: string | null, d: ICalDateTimeValue, dateonly?: boolean, floating?: boolean): string {
|
|
15
|
+
if(timezone?.startsWith('/')) {
|
|
16
|
+
timezone = timezone.substr(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if(typeof d === 'string' || d instanceof Date) {
|
|
20
|
+
const m = new Date(d);
|
|
21
|
+
|
|
22
|
+
// (!dateonly && !floating) || !timezone => utc
|
|
23
|
+
let s = m.getUTCFullYear() +
|
|
24
|
+
String(m.getUTCMonth() + 1).padStart(2, '0') +
|
|
25
|
+
m.getUTCDate().toString().padStart(2, '0');
|
|
26
|
+
|
|
27
|
+
// (dateonly || floating) && timezone => tz
|
|
28
|
+
if(timezone) {
|
|
29
|
+
s = m.getFullYear() +
|
|
30
|
+
String(m.getMonth() + 1).padStart(2, '0') +
|
|
31
|
+
m.getDate().toString().padStart(2, '0');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if(dateonly) {
|
|
35
|
+
return s;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if(timezone) {
|
|
39
|
+
s += 'T' + m.getHours().toString().padStart(2, '0') +
|
|
40
|
+
m.getMinutes().toString().padStart(2, '0') +
|
|
41
|
+
m.getSeconds().toString().padStart(2, '0');
|
|
42
|
+
|
|
43
|
+
return s;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
s += 'T' + m.getUTCHours().toString().padStart(2, '0') +
|
|
47
|
+
m.getUTCMinutes().toString().padStart(2, '0') +
|
|
48
|
+
m.getUTCSeconds().toString().padStart(2, '0') +
|
|
49
|
+
(floating ? '' : 'Z');
|
|
50
|
+
|
|
51
|
+
return s;
|
|
52
|
+
}
|
|
53
|
+
else if(isMoment(d)) {
|
|
54
|
+
// @see https://momentjs.com/timezone/docs/#/using-timezones/parsing-in-zone/
|
|
55
|
+
const m = timezone ? (isMomentTZ(d) && !d.tz() ? d.clone().tz(timezone) : d) : (floating ? d : d.utc());
|
|
56
|
+
return m.format('YYYYMMDD') + (!dateonly ? (
|
|
57
|
+
'T' + m.format('HHmmss') + (floating || timezone ? '' : 'Z')
|
|
58
|
+
) : '');
|
|
59
|
+
}
|
|
60
|
+
else if(isLuxonDate(d)) {
|
|
61
|
+
const m = timezone ? d.setZone(timezone) : (floating ? d : d.setZone('utc'));
|
|
62
|
+
return m.toFormat('yyyyLLdd') + (!dateonly ? (
|
|
63
|
+
'T' + m.toFormat('HHmmss') + (floating || timezone ? '' : 'Z')
|
|
64
|
+
) : '');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// @see https://day.js.org/docs/en/plugin/utc
|
|
68
|
+
|
|
69
|
+
let m = d;
|
|
70
|
+
if(timezone) {
|
|
71
|
+
// @see https://day.js.org/docs/en/plugin/timezone
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
m = typeof d.tz === 'function' ? d.tz(timezone) : d;
|
|
74
|
+
}
|
|
75
|
+
else if(floating) {
|
|
76
|
+
// m = d;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
else if (typeof d.utc === 'function') {
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
m = d.utc();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new Error('Unable to convert dayjs object to UTC value: UTC plugin is not available!');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return m.format('YYYYMMDD') + (!dateonly ? (
|
|
89
|
+
'T' + m.format('HHmmss') + (floating || timezone ? '' : 'Z')
|
|
90
|
+
) : '');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Converts a valid date/time object supported by this library to a string.
|
|
96
|
+
* For information about this format, see RFC 5545, section 3.3.5
|
|
97
|
+
* https://tools.ietf.org/html/rfc5545#section-3.3.5
|
|
98
|
+
*/
|
|
99
|
+
export function formatDateTZ (timezone: string | null, property: string, date: ICalDateTimeValue | Date | string, eventData?: {floating?: boolean | null, timezone?: string | null}): string {
|
|
100
|
+
let tzParam = '';
|
|
101
|
+
let floating = eventData?.floating || false;
|
|
102
|
+
|
|
103
|
+
if (eventData?.timezone) {
|
|
104
|
+
tzParam = ';TZID=' + eventData.timezone;
|
|
105
|
+
|
|
106
|
+
// This isn't a 'floating' event because it has a timezone;
|
|
107
|
+
// but we use it to omit the 'Z' UTC specifier in formatDate()
|
|
108
|
+
floating = true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return property + tzParam + ':' + formatDate(timezone, date, false, floating);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Escapes special characters in the given string
|
|
116
|
+
*/
|
|
117
|
+
export function escape (str: string | unknown, inQuotes: boolean): string {
|
|
118
|
+
return String(str).replace(inQuotes ? /[\\;,"]/g : /[\\;,]/g, function (match) {
|
|
119
|
+
return '\\' + match;
|
|
120
|
+
}).replace(/(?:\r\n|\r|\n)/g, '\\n');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Trim line length of given string
|
|
125
|
+
*/
|
|
126
|
+
export function foldLines (input: string): string {
|
|
127
|
+
return input.split('\r\n').map(function (line) {
|
|
128
|
+
let result = '';
|
|
129
|
+
let c = 0;
|
|
130
|
+
for (let i = 0; i < line.length; i++) {
|
|
131
|
+
let ch = line.charAt(i);
|
|
132
|
+
|
|
133
|
+
// surrogate pair, see https://mathiasbynens.be/notes/javascript-encoding#surrogate-pairs
|
|
134
|
+
if (ch >= '\ud800' && ch <= '\udbff') {
|
|
135
|
+
ch += line.charAt(++i);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// TextEncoder is available in browsers and node.js >= 11.0.0
|
|
139
|
+
const charsize = new TextEncoder().encode(ch).length;
|
|
140
|
+
c += charsize;
|
|
141
|
+
if (c > 74) {
|
|
142
|
+
result += '\r\n ';
|
|
143
|
+
c = charsize;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
result += ch;
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}).join('\r\n');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function addOrGetCustomAttributes (data: {x: [string, string][]}, keyOrArray: ({key: string, value: string})[] | [string, string][] | Record<string, string>): void;
|
|
153
|
+
export function addOrGetCustomAttributes (data: {x: [string, string][]}, keyOrArray: string, value: string): void;
|
|
154
|
+
export function addOrGetCustomAttributes (data: {x: [string, string][]}): ({key: string, value: string})[];
|
|
155
|
+
export function addOrGetCustomAttributes (data: {x: [string, string][]}, keyOrArray?: ({key: string, value: string})[] | [string, string][] | Record<string, string> | string | undefined, value?: string | undefined): void | ({key: string, value: string})[] {
|
|
156
|
+
if (Array.isArray(keyOrArray)) {
|
|
157
|
+
data.x = keyOrArray.map((o: {key: string, value: string} | [string, string]) => {
|
|
158
|
+
if(Array.isArray(o)) {
|
|
159
|
+
return o;
|
|
160
|
+
}
|
|
161
|
+
if (typeof o.key !== 'string' || typeof o.value !== 'string') {
|
|
162
|
+
throw new Error('Either key or value is not a string!');
|
|
163
|
+
}
|
|
164
|
+
if (o.key.substr(0, 2) !== 'X-') {
|
|
165
|
+
throw new Error('Key has to start with `X-`!');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return [o.key, o.value] as [string, string];
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else if (typeof keyOrArray === 'object') {
|
|
172
|
+
data.x = Object.entries(keyOrArray).map(([key, value]) => {
|
|
173
|
+
if (typeof key !== 'string' || typeof value !== 'string') {
|
|
174
|
+
throw new Error('Either key or value is not a string!');
|
|
175
|
+
}
|
|
176
|
+
if (key.substr(0, 2) !== 'X-') {
|
|
177
|
+
throw new Error('Key has to start with `X-`!');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return [key, value];
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
else if (typeof keyOrArray === 'string' && typeof value === 'string') {
|
|
184
|
+
if (keyOrArray.substr(0, 2) !== 'X-') {
|
|
185
|
+
throw new Error('Key has to start with `X-`!');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
data.x.push([keyOrArray, value]);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
return data.x.map(a => ({
|
|
192
|
+
key: a[0],
|
|
193
|
+
value: a[1]
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function generateCustomAttributes (data: {x: [string, string][]}): string {
|
|
199
|
+
const str = data.x
|
|
200
|
+
.map(([key, value]) => key.toUpperCase() + ':' + escape(value, false))
|
|
201
|
+
.join('\r\n');
|
|
202
|
+
return str.length ? str + '\r\n' : '';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Check the given string or ICalOrganizer. Parses
|
|
207
|
+
* the string for name and email address if possible.
|
|
208
|
+
*
|
|
209
|
+
* @param attribute Attribute name for error messages
|
|
210
|
+
* @param value Value to parse name/email from
|
|
211
|
+
*/
|
|
212
|
+
export function checkNameAndMail (attribute: string, value: string | ICalOrganizer): ICalOrganizer {
|
|
213
|
+
let result: ICalOrganizer | null = null;
|
|
214
|
+
|
|
215
|
+
if (typeof value === 'string') {
|
|
216
|
+
const match = value.match(/^(.+) ?<([^>]+)>$/);
|
|
217
|
+
if (match) {
|
|
218
|
+
result = {
|
|
219
|
+
name: match[1].trim(),
|
|
220
|
+
email: match[2].trim()
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
else if(value.includes('@')) {
|
|
224
|
+
result = {
|
|
225
|
+
name: value.trim(),
|
|
226
|
+
email: value.trim()
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (typeof value === 'object') {
|
|
231
|
+
result = {
|
|
232
|
+
name: value.name,
|
|
233
|
+
email: value.email,
|
|
234
|
+
mailto: value.mailto,
|
|
235
|
+
sentBy: value.sentBy
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!result && typeof value === 'string') {
|
|
240
|
+
throw new Error(
|
|
241
|
+
'`' + attribute + '` isn\'t formated correctly. See https://sebbo2002.github.io/ical-generator/develop/'+
|
|
242
|
+
'reference/interfaces/ICalOrganizer.html'
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
else if (!result) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
'`' + attribute + '` needs to be a valid formed string or an object. See https://sebbo2002.github.io/'+
|
|
248
|
+
'ical-generator/develop/reference/interfaces/ICalOrganizer.html'
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (!result.name) {
|
|
253
|
+
throw new Error('`' + attribute + '.name` is empty!');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Checks if the given string `value` is a
|
|
261
|
+
* valid one for the type `type`
|
|
262
|
+
*/
|
|
263
|
+
export function checkEnum(type: Record<string, string>, value: unknown): unknown {
|
|
264
|
+
const allowedValues = Object.values(type);
|
|
265
|
+
const valueStr = String(value).toUpperCase();
|
|
266
|
+
|
|
267
|
+
if (!valueStr || !allowedValues.includes(valueStr)) {
|
|
268
|
+
throw new Error(`Input must be one of the following: ${allowedValues.join(', ')}`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return valueStr;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Checks if the given input is a valid date and
|
|
276
|
+
* returns the internal representation (= moment object)
|
|
277
|
+
*/
|
|
278
|
+
export function checkDate(value: ICalDateTimeValue, attribute: string): ICalDateTimeValue {
|
|
279
|
+
|
|
280
|
+
// Date & String
|
|
281
|
+
if(
|
|
282
|
+
(value instanceof Date && isNaN(value.getTime())) ||
|
|
283
|
+
(typeof value === 'string' && isNaN(new Date(value).getTime()))
|
|
284
|
+
) {
|
|
285
|
+
throw new Error(`\`${attribute}\` has to be a valid date!`);
|
|
286
|
+
}
|
|
287
|
+
if(value instanceof Date || typeof value === 'string') {
|
|
288
|
+
return value;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Luxon
|
|
292
|
+
if(isLuxonDate(value) && value.isValid === true) {
|
|
293
|
+
return value;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Moment / Moment Timezone
|
|
297
|
+
if((isMoment(value) || isDayjs(value)) && value.isValid()) {
|
|
298
|
+
return value;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
throw new Error(`\`${attribute}\` has to be a valid date!`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function toDate(value: ICalDateTimeValue): Date {
|
|
305
|
+
if(typeof value === 'string' || value instanceof Date) {
|
|
306
|
+
return new Date(value);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// @ts-ignore
|
|
310
|
+
if(isLuxonDate(value)) {
|
|
311
|
+
return value.toJSDate();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return value.toDate();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export function isMoment(value: ICalDateTimeValue): value is ICalMomentStub {
|
|
318
|
+
|
|
319
|
+
// @ts-ignore
|
|
320
|
+
return value != null && value._isAMomentObject != null;
|
|
321
|
+
}
|
|
322
|
+
export function isMomentTZ(value: ICalDateTimeValue): value is ICalMomentTimezoneStub {
|
|
323
|
+
return isMoment(value) && 'tz' in value && typeof value.tz === 'function';
|
|
324
|
+
}
|
|
325
|
+
export function isDayjs(value: ICalDateTimeValue): value is ICalDayJsStub {
|
|
326
|
+
return typeof value === 'object' &&
|
|
327
|
+
value !== null &&
|
|
328
|
+
!(value instanceof Date) &&
|
|
329
|
+
!isMoment(value) &&
|
|
330
|
+
!isLuxonDate(value);
|
|
331
|
+
}
|
|
332
|
+
export function isLuxonDate(value: ICalDateTimeValue): value is ICalLuxonDateTimeStub {
|
|
333
|
+
return typeof value === 'object' && value !== null && 'toJSDate' in value && typeof value.toJSDate === 'function';
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export function isMomentDuration(value: unknown): value is ICalMomentDurationStub {
|
|
337
|
+
|
|
338
|
+
// @ts-ignore
|
|
339
|
+
return value !== null && typeof value === 'object' && typeof value.asSeconds === 'function';
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function isRRule(value: unknown): value is ICalRRuleStub {
|
|
343
|
+
|
|
344
|
+
// @ts-ignore
|
|
345
|
+
return value !== null && typeof value === 'object' && typeof value.between === 'function' && typeof value.toString === 'function';
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export function toJSON(value: ICalDateTimeValue | null | undefined): string | null | undefined {
|
|
349
|
+
if(!value) {
|
|
350
|
+
return value;
|
|
351
|
+
}
|
|
352
|
+
if(typeof value === 'string') {
|
|
353
|
+
return value;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return value.toJSON();
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export function toDurationString(seconds: number): string {
|
|
360
|
+
let string = '';
|
|
361
|
+
|
|
362
|
+
// < 0
|
|
363
|
+
if(seconds < 0) {
|
|
364
|
+
string = '-';
|
|
365
|
+
seconds *= -1;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
string += 'P';
|
|
369
|
+
|
|
370
|
+
// DAYS
|
|
371
|
+
if(seconds >= 86400) {
|
|
372
|
+
string += Math.floor(seconds / 86400) + 'D';
|
|
373
|
+
seconds %= 86400;
|
|
374
|
+
}
|
|
375
|
+
if(!seconds && string.length > 1) {
|
|
376
|
+
return string;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
string += 'T';
|
|
380
|
+
|
|
381
|
+
// HOURS
|
|
382
|
+
if(seconds >= 3600) {
|
|
383
|
+
string += Math.floor(seconds / 3600) + 'H';
|
|
384
|
+
seconds %= 3600;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// MINUTES
|
|
388
|
+
if(seconds >= 60) {
|
|
389
|
+
string += Math.floor(seconds / 60) + 'M';
|
|
390
|
+
seconds %= 60;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// SECONDS
|
|
394
|
+
if(seconds > 0) {
|
|
395
|
+
string += seconds + 'S';
|
|
396
|
+
}
|
|
397
|
+
else if(string.length <= 2) {
|
|
398
|
+
string += '0S';
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return string;
|
|
402
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ical-generator supports [native Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date),
|
|
3
|
+
* [moment.js](https://momentjs.com/) (and [moment-timezone](https://momentjs.com/timezone/), [Day.js](https://day.js.org/en/) and
|
|
4
|
+
* [Luxon](https://moment.github.io/luxon/)'s [DateTime](https://moment.github.io/luxon/docs/class/src/datetime.js~DateTime.html)
|
|
5
|
+
* objects. You can also pass a string which is then passed to javascript's Date internally.
|
|
6
|
+
*/
|
|
7
|
+
export type ICalDateTimeValue = Date | ICalMomentStub | ICalMomentTimezoneStub | ICalLuxonDateTimeStub | ICalDayJsStub | string;
|
|
8
|
+
|
|
9
|
+
export interface ICalRepeatingOptions {
|
|
10
|
+
freq: ICalEventRepeatingFreq;
|
|
11
|
+
count?: number;
|
|
12
|
+
interval?: number;
|
|
13
|
+
until?: ICalDateTimeValue;
|
|
14
|
+
byDay?: ICalWeekday[] | ICalWeekday;
|
|
15
|
+
byMonth?: number[] | number;
|
|
16
|
+
byMonthDay?: number[] | number;
|
|
17
|
+
bySetPos?: number;
|
|
18
|
+
exclude?: ICalDateTimeValue[] | ICalDateTimeValue;
|
|
19
|
+
startOfWeek?: ICalWeekday;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ICalLocation {
|
|
23
|
+
title: string;
|
|
24
|
+
address?: string;
|
|
25
|
+
radius?: number;
|
|
26
|
+
geo?: ICalGeo;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ICalGeo {
|
|
30
|
+
lat: number;
|
|
31
|
+
lon: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ICalOrganizer {
|
|
35
|
+
name: string;
|
|
36
|
+
email?: string;
|
|
37
|
+
mailto?: string;
|
|
38
|
+
sentBy?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ICalDescription {
|
|
42
|
+
plain: string;
|
|
43
|
+
html?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ICalTimezone {
|
|
47
|
+
name: string | null;
|
|
48
|
+
generator?: (timezone: string) => string|null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface ICalMomentStub {
|
|
52
|
+
format(format?: string): string;
|
|
53
|
+
clone(): ICalMomentStub;
|
|
54
|
+
utc(): ICalMomentStub;
|
|
55
|
+
toDate(): Date;
|
|
56
|
+
isValid(): boolean;
|
|
57
|
+
toJSON(): string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ICalMomentTimezoneStub extends ICalMomentStub {
|
|
61
|
+
clone(): ICalMomentTimezoneStub;
|
|
62
|
+
utc(): ICalMomentTimezoneStub;
|
|
63
|
+
tz(): string | undefined;
|
|
64
|
+
tz(timezone: string): ICalMomentTimezoneStub;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface ICalMomentDurationStub {
|
|
68
|
+
asSeconds(): number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface ICalLuxonDateTimeStub {
|
|
72
|
+
setZone(zone?: string): ICalLuxonDateTimeStub;
|
|
73
|
+
toFormat(fmt: string): string;
|
|
74
|
+
toJSDate(): Date;
|
|
75
|
+
get isValid(): boolean;
|
|
76
|
+
toJSON(): string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface ICalDayJsStub {
|
|
80
|
+
tz(zone?: string): ICalDayJsStub;
|
|
81
|
+
utc(): ICalDayJsStub;
|
|
82
|
+
format(format?: string): string;
|
|
83
|
+
toDate(): Date;
|
|
84
|
+
isValid(): boolean;
|
|
85
|
+
toJSON(): string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ICalRRuleStub {
|
|
89
|
+
between(after: Date, before: Date, inc?: boolean, iterator?: (d: Date, len: number) => boolean): Date[];
|
|
90
|
+
toString(): string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export enum ICalEventRepeatingFreq {
|
|
94
|
+
SECONDLY = 'SECONDLY',
|
|
95
|
+
MINUTELY = 'MINUTELY',
|
|
96
|
+
HOURLY = 'HOURLY',
|
|
97
|
+
DAILY = 'DAILY',
|
|
98
|
+
WEEKLY = 'WEEKLY',
|
|
99
|
+
MONTHLY = 'MONTHLY',
|
|
100
|
+
YEARLY = 'YEARLY'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export enum ICalWeekday {
|
|
104
|
+
SU = 'SU',
|
|
105
|
+
MO = 'MO',
|
|
106
|
+
TU = 'TU',
|
|
107
|
+
WE = 'WE',
|
|
108
|
+
TH = 'TH',
|
|
109
|
+
FR = 'FR',
|
|
110
|
+
SA = 'SA'
|
|
111
|
+
}
|