iamcal 1.0.2 → 1.0.3

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/README.md CHANGED
@@ -10,9 +10,11 @@ A library for reading, modifying and writing [ICalendar](https://en.wikipedia.or
10
10
  npm install iamcal
11
11
  ```
12
12
 
13
- ## Getting started/Example
13
+ ## Getting started
14
14
 
15
- This code;
15
+ ### Parsing and editing a calendar
16
+
17
+ This code:
16
18
 
17
19
  ```typescript
18
20
  import { Calendar } from 'iamcal'
@@ -58,4 +60,6 @@ DTSTART:20241211T200000Z
58
60
  DTEND:20241211T230000Z
59
61
  END:VEVENT
60
62
  END:VCALENDAR
61
- ```
63
+ ```
64
+
65
+ ### Creating a new calendar
package/lib/index.d.ts CHANGED
@@ -1,36 +1,137 @@
1
- export interface Property {
2
- name: string;
3
- params: string[];
4
- value: string;
5
- }
1
+ import { Property } from './types';
6
2
  export declare class Component {
7
3
  name: string;
8
- properties: Array<Property>;
9
- components: Array<Component>;
10
- constructor(name: string, properties?: Array<Property>, components?: Array<Component>);
4
+ properties: Property[];
5
+ components: Component[];
6
+ constructor(name: string, properties?: Property[], components?: Component[]);
11
7
  serialize(): string;
12
8
  getProperty(name: string): Property | null;
13
9
  setProperty(name: string, value: string): void;
10
+ removePropertiesWithName(name: string): void;
14
11
  getPropertyParams(name: string): string[] | null;
15
12
  setPropertyParams(name: string, params: string[]): void;
13
+ addComponent(component: Component): void;
14
+ removeComponent(component: Component): boolean;
15
+ getComponents(name: string): Component[];
16
16
  }
17
+ /**
18
+ * Represents a VCALENDAR component, the root component of an iCalendar file.
19
+ */
17
20
  export declare class Calendar extends Component {
18
21
  name: string;
22
+ /**
23
+ * @param prodid A unique identifier of the program creating the calendar.
24
+ *
25
+ * Example: `-//Google Inc//Google Calendar 70.9054//EN`
26
+ */
27
+ constructor(prodid: string);
28
+ /**
29
+ * @param prodid A unique identifier of the program creating the calendar.
30
+ *
31
+ * Example: `-//Google Inc//Google Calendar 70.9054//EN`
32
+ * @param version The version of the iCalendar specification that this calendar uses.
33
+ */
34
+ constructor(prodid: string, version: string);
35
+ /**
36
+ * @param component A VCALENDAR component.
37
+ */
38
+ constructor(component: Component);
39
+ events(): CalendarEvent[];
40
+ removeEvent(event: CalendarEvent): boolean;
41
+ removeEvent(uid: string): boolean;
42
+ prodId(): string;
43
+ setProdId(value: string): void;
44
+ version(): string;
45
+ setVersion(value: string): void;
46
+ calScale(): string | undefined;
47
+ setCalScale(value: string): void;
48
+ removeCalScale(): void;
49
+ method(): string | undefined;
50
+ setMethod(value: string): void;
51
+ removeMethod(): void;
52
+ calendarName(): string | undefined;
53
+ setCalendarName(value: string): void;
54
+ removeCalendarName(): void;
55
+ calendarDescription(): string | undefined;
56
+ setCalendarDescription(value: string): void;
57
+ removeCalendarDescription(): void;
58
+ }
59
+ /**
60
+ * Represents a VTIMEZONE component, containing time zone definitions.
61
+ */
62
+ export declare class TimeZone extends Component {
63
+ constructor(id: string);
19
64
  constructor(component: Component);
20
- events(): Array<CalendarEvent>;
65
+ id(): string;
66
+ setId(value: string): void;
67
+ lastMod(): Date | undefined;
68
+ setLastMod(value: Date): void;
69
+ removeLastMod(): void;
70
+ url(): string | undefined;
71
+ setUrl(value: string): void;
72
+ removeUrl(): void;
73
+ /** Get all time offsets. */
74
+ offsets(): TimeZoneOffset[];
75
+ /** Get standard/winter time offsets. */
76
+ standardOffsets(): TimeZoneOffset[];
77
+ /** Get daylight savings time offsets. */
78
+ daylightOffsets(): TimeZoneOffset[];
79
+ }
80
+ export type OffsetType = 'DAYLIGHT' | 'STANDARD';
81
+ type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
82
+ export type Offset = `${'-' | '+'}${Digit}${Digit}${Digit}${Digit}`;
83
+ /** Represents a STANDARD or DAYLIGHT component, defining a time zone offset. */
84
+ declare class TimeZoneOffset extends Component {
85
+ /**
86
+ *
87
+ * @param type If this is a STANDARD or DAYLIGHT component.
88
+ * @param start From when this offset is active.
89
+ * @param offsetFrom The offset that is in use prior to this time zone observance.
90
+ * @param offsetTo The offset that is in use during this time zone observance.
91
+ */
92
+ constructor(type: OffsetType, start: Date, offsetFrom: Offset, offsetTo: Offset);
93
+ constructor(component: Component);
94
+ start(): Date;
95
+ setStart(value: Date): void;
96
+ offsetFrom(): Offset;
97
+ setOffsetFrom(value: Offset): void;
98
+ offsetTo(): Offset;
99
+ setOffsetTo(value: Offset): void;
100
+ comment(): string | undefined;
101
+ setComment(value: string): void;
102
+ removeComment(): void;
103
+ timeZoneName(): string | undefined;
104
+ setTimeZoneName(value: string): void;
105
+ removeTimeZoneName(): void;
21
106
  }
22
107
  export declare class CalendarEvent extends Component {
23
108
  name: string;
109
+ constructor(uid: string, dtstamp: Date);
24
110
  constructor(component: Component);
111
+ stamp(): Date;
112
+ setStamp(value: Date): void;
113
+ uid(): string;
114
+ setUid(value: string): void;
25
115
  summary(): string;
26
116
  setSummary(value: string): void;
117
+ removeSummary(): void;
27
118
  description(): string;
28
119
  setDescription(value: string): void;
120
+ removeDescription(): void;
29
121
  location(): string | undefined;
30
122
  setLocation(value: string): void;
123
+ removeLocation(): void;
31
124
  start(): Date;
32
125
  setStart(value: Date): void;
126
+ removeStart(): void;
33
127
  end(): Date;
34
128
  setEnd(value: Date): void;
129
+ removeEnd(): void;
130
+ created(): Date | undefined;
131
+ setCreated(value: Date): void;
132
+ removeCreated(): void;
133
+ geo(): [number, number] | undefined;
134
+ setGeo(latitude: number, longitude: number): void;
35
135
  }
136
+ export {};
36
137
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CAChB;AAKD,qBAAa,SAAS;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;IAC3B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;gBAEhB,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAcrF,SAAS,IAAI,MAAM;IA+BnB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAS1C,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAcvC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI;IAShD,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;CAOnD;AAED,qBAAa,QAAS,SAAQ,SAAS;IACnC,IAAI,SAAc;gBAEN,SAAS,EAAE,SAAS;IAIhC,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC;CAWjC;AAED,qBAAa,aAAc,SAAQ,SAAS;IACxC,IAAI,SAAW;gBAEH,SAAS,EAAE,SAAS;IAIhC,OAAO,IAAI,MAAM;IAIjB,UAAU,CAAC,KAAK,EAAE,MAAM;IAIxB,WAAW,IAAI,MAAM;IAIrB,cAAc,CAAC,KAAK,EAAE,MAAM;IAI5B,QAAQ,IAAI,MAAM,GAAG,SAAS;IAI9B,WAAW,CAAC,KAAK,EAAE,MAAM;IAIzB,KAAK,IAAI,IAAI;IAIb,QAAQ,CAAC,KAAK,EAAE,IAAI;IAIpB,GAAG,IAAI,IAAI;IAIX,MAAM,CAAC,KAAK,EAAE,IAAI;CAGrB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CalendarEvent = exports.Calendar = exports.Component = void 0;
3
+ exports.CalendarEvent = exports.TimeZone = exports.Calendar = exports.Component = void 0;
4
4
  // Max line length as defined by RFC 5545 3.1.
5
5
  const MAX_LINE_LENGTH = 75;
6
6
  class Component {
@@ -33,7 +33,7 @@ class Component {
33
33
  // Wrap lines
34
34
  while (line.length > MAX_LINE_LENGTH) {
35
35
  lines.push(line.substring(0, MAX_LINE_LENGTH));
36
- line = " " + line.substring(MAX_LINE_LENGTH);
36
+ line = ' ' + line.substring(MAX_LINE_LENGTH);
37
37
  }
38
38
  lines.push(line);
39
39
  }
@@ -66,6 +66,13 @@ class Component {
66
66
  value: value,
67
67
  });
68
68
  }
69
+ removePropertiesWithName(name) {
70
+ const index = this.properties.findIndex(p => p.name === name);
71
+ if (index === -1)
72
+ return;
73
+ // Remove property at index
74
+ this.properties.splice(index, 1);
75
+ }
69
76
  getPropertyParams(name) {
70
77
  for (const property of this.properties) {
71
78
  if (property.name === name) {
@@ -81,59 +88,332 @@ class Component {
81
88
  }
82
89
  }
83
90
  }
91
+ addComponent(component) {
92
+ this.components.push(component);
93
+ }
94
+ removeComponent(component) {
95
+ const index = this.components.indexOf(component);
96
+ if (index === -1)
97
+ return false;
98
+ // Remove element at index from list
99
+ this.components.splice(index, 1);
100
+ return true;
101
+ }
102
+ getComponents(name) {
103
+ const components = [];
104
+ for (let component of this.components) {
105
+ if (component.name === name) {
106
+ components.push(component);
107
+ }
108
+ }
109
+ return components;
110
+ }
84
111
  }
85
112
  exports.Component = Component;
113
+ /**
114
+ * Represents a VCALENDAR component, the root component of an iCalendar file.
115
+ */
86
116
  class Calendar extends Component {
87
117
  name = 'VCALENDAR';
88
- constructor(component) {
118
+ constructor(a, b) {
119
+ var component;
120
+ if (a instanceof Component) {
121
+ component = a;
122
+ }
123
+ else {
124
+ const prodid = a;
125
+ const version = b ?? '2.0';
126
+ component = new Component('VCALENDAR');
127
+ component.setProperty('PRODID', prodid);
128
+ component.setProperty('VERSION', version);
129
+ }
89
130
  super(component.name, component.properties, component.components);
90
131
  }
91
132
  events() {
92
- const events = new Array();
93
- for (let component of this.components) {
94
- if (component.name === 'VEVENT') {
95
- events.push(new CalendarEvent(component));
133
+ return this.getComponents('VEVENT').map(c => new CalendarEvent(c));
134
+ }
135
+ removeEvent(a) {
136
+ if (a instanceof CalendarEvent) {
137
+ const event = a;
138
+ return this.removeComponent(event);
139
+ }
140
+ else {
141
+ const uid = a;
142
+ for (const event of this.events()) {
143
+ if (event.uid() !== uid)
144
+ continue;
145
+ return this.removeComponent(event);
96
146
  }
97
147
  }
98
- return events;
148
+ return false;
149
+ }
150
+ prodId() {
151
+ return this.getProperty('PRODID').value;
152
+ }
153
+ setProdId(value) {
154
+ this.setProperty('PRODID', value);
155
+ }
156
+ version() {
157
+ return this.getProperty('VERSION').value;
158
+ }
159
+ setVersion(value) {
160
+ this.setProperty('VERSION', value);
161
+ }
162
+ calScale() {
163
+ return this.getProperty('CALSCALE')?.value;
164
+ }
165
+ setCalScale(value) {
166
+ this.setProperty('CALSCALE', value);
167
+ }
168
+ removeCalScale() {
169
+ this.removePropertiesWithName('CALSCALE');
170
+ }
171
+ method() {
172
+ return this.getProperty('METHOD')?.value;
173
+ }
174
+ setMethod(value) {
175
+ this.setProperty('METHOD', value);
176
+ }
177
+ removeMethod() {
178
+ this.removePropertiesWithName('METHOD');
179
+ }
180
+ calendarName() {
181
+ return this.getProperty('X-WR-CALNAME')?.value;
182
+ }
183
+ setCalendarName(value) {
184
+ this.setProperty('X-WR-CALNAME', value);
185
+ }
186
+ removeCalendarName() {
187
+ this.removePropertiesWithName('X-WR-CALNAME');
188
+ }
189
+ calendarDescription() {
190
+ return this.getProperty('X-WR-CALDESC')?.value;
191
+ }
192
+ setCalendarDescription(value) {
193
+ this.setProperty('X-WR-CALDESC', value);
194
+ }
195
+ removeCalendarDescription() {
196
+ this.removePropertiesWithName('X-WR-CALDESC');
99
197
  }
100
198
  }
101
199
  exports.Calendar = Calendar;
200
+ /**
201
+ * Represents a VTIMEZONE component, containing time zone definitions.
202
+ */
203
+ class TimeZone extends Component {
204
+ constructor(a) {
205
+ var component;
206
+ if (a instanceof Component) {
207
+ component = a;
208
+ }
209
+ else {
210
+ const tzid = a;
211
+ component = new Component('VTIMEZONE');
212
+ component.setProperty('TZID', tzid);
213
+ }
214
+ super(component.name, component.properties, component.components);
215
+ }
216
+ id() {
217
+ return this.getProperty('TZID').value;
218
+ }
219
+ setId(value) {
220
+ this.setProperty('TZID', value);
221
+ }
222
+ lastMod() {
223
+ const text = this.getProperty('LAST-MOD');
224
+ if (!text)
225
+ return;
226
+ return new Date(text.value);
227
+ }
228
+ setLastMod(value) {
229
+ this.setProperty('LAST-MOD', value.toISOString());
230
+ }
231
+ removeLastMod() {
232
+ this.removePropertiesWithName('LAST-MOD');
233
+ }
234
+ url() {
235
+ return this.getProperty('TZURL')?.value;
236
+ }
237
+ setUrl(value) {
238
+ this.setProperty('TZURL', value);
239
+ }
240
+ removeUrl() {
241
+ this.removePropertiesWithName('TZURL');
242
+ }
243
+ /** Get all time offsets. */
244
+ offsets() {
245
+ const offsets = [];
246
+ this.components.forEach(component => {
247
+ if (component.name === 'STANDARD' || component.name === 'DAYLIGHT') {
248
+ offsets.push(new TimeZoneOffset(component));
249
+ }
250
+ });
251
+ return offsets;
252
+ }
253
+ /** Get standard/winter time offsets. */
254
+ standardOffsets() {
255
+ return this.getComponents('STANDARD').map(c => new TimeZoneOffset(c));
256
+ }
257
+ /** Get daylight savings time offsets. */
258
+ daylightOffsets() {
259
+ return this.getComponents('DAYLIGHT').map(c => new TimeZoneOffset(c));
260
+ }
261
+ }
262
+ exports.TimeZone = TimeZone;
263
+ /** Represents a STANDARD or DAYLIGHT component, defining a time zone offset. */
264
+ class TimeZoneOffset extends Component {
265
+ constructor(a, b, c, d) {
266
+ var component;
267
+ if (a instanceof Component) {
268
+ component = a;
269
+ }
270
+ else {
271
+ const name = a;
272
+ const start = b;
273
+ const offsetFrom = c;
274
+ const offsetTo = d;
275
+ component = new Component(name);
276
+ component.setProperty('DTSTART', start.toISOString());
277
+ component.setProperty('TZOFFSETFROM', offsetFrom);
278
+ component.setProperty('TZOFFSETTO', offsetTo);
279
+ }
280
+ super(component.name, component.properties, component.components);
281
+ }
282
+ start() {
283
+ return new Date(this.getProperty('DTSTART').value);
284
+ }
285
+ setStart(value) {
286
+ this.setProperty('DTSTART', value.toISOString());
287
+ }
288
+ offsetFrom() {
289
+ return this.getProperty('TZOFFSETFROM').value;
290
+ }
291
+ setOffsetFrom(value) {
292
+ this.setProperty('TZOFFSETFROM', value);
293
+ }
294
+ offsetTo() {
295
+ return this.getProperty('TZOFFSETTO').value;
296
+ }
297
+ setOffsetTo(value) {
298
+ this.setProperty('TZOFFSETTO', value);
299
+ }
300
+ comment() {
301
+ return this.getProperty('COMMENT')?.value;
302
+ }
303
+ setComment(value) {
304
+ this.setProperty('COMMENT', value);
305
+ }
306
+ removeComment() {
307
+ this.removePropertiesWithName('COMMENT');
308
+ }
309
+ timeZoneName() {
310
+ return this.getProperty('TZNAME')?.value;
311
+ }
312
+ setTimeZoneName(value) {
313
+ this.setProperty('TZNAME', value);
314
+ }
315
+ removeTimeZoneName() {
316
+ this.removePropertiesWithName('TZNAME');
317
+ }
318
+ }
102
319
  class CalendarEvent extends Component {
103
320
  name = 'VEVENT';
104
- constructor(component) {
321
+ constructor(a, b) {
322
+ var component;
323
+ if (b) {
324
+ const uid = a;
325
+ const dtstamp = b;
326
+ component = new Component('VEVENT');
327
+ component.setProperty('UID', uid);
328
+ component.setProperty('DTSTAMP', dtstamp.toISOString());
329
+ }
330
+ else {
331
+ component = a;
332
+ }
105
333
  super(component.name, component.properties, component.components);
106
334
  }
335
+ stamp() {
336
+ return new Date(this.getProperty('DTSTAMP').value);
337
+ }
338
+ setStamp(value) {
339
+ this.setProperty('DTSTAMP', value.toISOString());
340
+ }
341
+ uid() {
342
+ return this.getProperty('UID').value;
343
+ }
344
+ setUid(value) {
345
+ this.setProperty('UID', value);
346
+ }
107
347
  summary() {
108
348
  return this.getProperty('SUMMARY').value;
109
349
  }
110
350
  setSummary(value) {
111
- this.setProperty("SUMMARY", value);
351
+ this.setProperty('SUMMARY', value);
352
+ }
353
+ removeSummary() {
354
+ this.removePropertiesWithName('SUMMARY');
112
355
  }
113
356
  description() {
114
357
  return this.getProperty('DESCRIPTION').value;
115
358
  }
116
359
  setDescription(value) {
117
- this.setProperty("DESCRIPTION", value);
360
+ this.setProperty('DESCRIPTION', value);
361
+ }
362
+ removeDescription() {
363
+ this.removePropertiesWithName('DESCRIPTION');
118
364
  }
119
365
  location() {
120
366
  return this.getProperty('LOCATION')?.value;
121
367
  }
122
368
  setLocation(value) {
123
- this.setProperty("LOCATION", value);
369
+ this.setProperty('LOCATION', value);
370
+ }
371
+ removeLocation() {
372
+ this.removePropertiesWithName('LOCATION');
124
373
  }
125
374
  start() {
126
375
  return new Date(this.getProperty('DTSTART').value);
127
376
  }
128
377
  setStart(value) {
129
- this.setProperty("DTSTART", value.toISOString());
378
+ this.setProperty('DTSTART', value.toISOString());
379
+ }
380
+ removeStart() {
381
+ this.removePropertiesWithName('DTSTART');
130
382
  }
131
383
  end() {
132
384
  return new Date(this.getProperty('DTEND').value);
133
385
  }
134
386
  setEnd(value) {
135
- this.setProperty("DTEND", value.toISOString());
387
+ this.setProperty('DTEND', value.toISOString());
388
+ }
389
+ removeEnd() {
390
+ this.removePropertiesWithName('DTEND');
391
+ }
392
+ created() {
393
+ const text = this.getProperty('CREATED')?.value;
394
+ if (!text)
395
+ return;
396
+ return new Date(text);
397
+ }
398
+ setCreated(value) {
399
+ this.setProperty('CREATED', value.toISOString());
400
+ }
401
+ removeCreated() {
402
+ this.removePropertiesWithName('CREATED');
403
+ }
404
+ geo() {
405
+ const text = this.getProperty('GEO')?.value;
406
+ if (!text)
407
+ return;
408
+ const pattern = /^[+-]?\d+(\.\d+)?,[+-]?\d+(\.\d+)?$/;
409
+ if (!pattern.test(text))
410
+ throw new Error(`Failed to parse GEO property: ${text}`);
411
+ const [longitude, latitude] = text.split(',');
412
+ return [parseFloat(longitude), parseFloat(latitude)];
413
+ }
414
+ setGeo(latitude, longitude) {
415
+ const text = `${latitude},${longitude}`;
136
416
  }
137
417
  }
138
418
  exports.CalendarEvent = CalendarEvent;
139
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBTUEsOENBQThDO0FBQzlDLE1BQU0sZUFBZSxHQUFHLEVBQUUsQ0FBQTtBQUUxQixNQUFhLFNBQVM7SUFDbEIsSUFBSSxDQUFRO0lBQ1osVUFBVSxDQUFpQjtJQUMzQixVQUFVLENBQWtCO0lBRTVCLFlBQVksSUFBWSxFQUFFLFVBQTRCLEVBQUUsVUFBNkI7UUFDakYsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUE7UUFDaEIsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQ2hDLENBQUM7YUFBTSxDQUFDO1lBQ0osSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFBO1FBQ2pDLENBQUM7UUFDRCxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUE7UUFDaEMsQ0FBQzthQUFNLENBQUM7WUFDSixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUE7UUFDakMsQ0FBQztJQUNMLENBQUM7SUFFRCxTQUFTO1FBQ0wsZUFBZTtRQUNmLE1BQU0sS0FBSyxHQUFHLENBQUMsU0FBUyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQTtRQUVwQyxLQUFLLElBQUksUUFBUSxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNuQyxJQUFJLElBQUksR0FDSixRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRTtnQkFDckIsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDMUMsR0FBRztnQkFDSCxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUE7WUFF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
419
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsOENBQThDO0FBQzlDLE1BQU0sZUFBZSxHQUFHLEVBQUUsQ0FBQTtBQUUxQixNQUFhLFNBQVM7SUFDbEIsSUFBSSxDQUFRO0lBQ1osVUFBVSxDQUFZO0lBQ3RCLFVBQVUsQ0FBYTtJQUV2QixZQUFZLElBQVksRUFBRSxVQUF1QixFQUFFLFVBQXdCO1FBQ3ZFLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFBO1FBQ2hCLElBQUksVUFBVSxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQTtRQUNoQyxDQUFDO2FBQU0sQ0FBQztZQUNKLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQTtRQUNqQyxDQUFDO1FBQ0QsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQ2hDLENBQUM7YUFBTSxDQUFDO1lBQ0osSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFBO1FBQ2pDLENBQUM7SUFDTCxDQUFDO0lBRUQsU0FBUztRQUNMLGVBQWU7UUFDZixNQUFNLEtBQUssR0FBRyxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUE7UUFFcEMsS0FBSyxJQUFJLFFBQVEsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbkMsSUFBSSxJQUFJLEdBQ0osUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7Z0JBQ3JCLFFBQVEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQzFDLEdBQUc7Z0JBQ0gsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBRXJC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
package/lib/types.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export interface Property {
2
+ name: string;
3
+ params: string[];
4
+ value: string;
5
+ }
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CAChB"}
package/lib/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
package/package.json CHANGED
@@ -1,16 +1,27 @@
1
1
  {
2
2
  "name": "iamcal",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Read and write ICalendar files",
5
5
  "files": [
6
6
  "/lib",
7
7
  "/src"
8
8
  ],
9
9
  "exports": {
10
- ".": "./lib/index.js",
11
- "./parse": "./lib/parse.js",
12
- "./io": "./lib/io.js"
10
+ ".": {
11
+ "default": "./lib/index.js",
12
+ "types": "./lib/index.d.ts"
13
+ },
14
+ "./parse": {
15
+ "default": "./lib/parse.js",
16
+ "types": "./lib/parse.d.ts"
17
+ },
18
+ "./io": {
19
+ "default": "./lib/io.js",
20
+ "types": "./lib/io.d.ts"
21
+ }
13
22
  },
23
+ "main": "./lib/index.js",
24
+ "types": "./lib/index.d.ts",
14
25
  "scripts": {
15
26
  "build": "rimraf lib && tsc",
16
27
  "test": "echo \"Error: no test specified\" && exit 1"
package/src/index.ts CHANGED
@@ -1,18 +1,14 @@
1
- export interface Property {
2
- name: string
3
- params: string[]
4
- value: string
5
- }
1
+ import { Property } from './types'
6
2
 
7
3
  // Max line length as defined by RFC 5545 3.1.
8
4
  const MAX_LINE_LENGTH = 75
9
5
 
10
6
  export class Component {
11
7
  name: string
12
- properties: Array<Property>
13
- components: Array<Component>
8
+ properties: Property[]
9
+ components: Component[]
14
10
 
15
- constructor(name: string, properties?: Array<Property>, components?: Array<Component>) {
11
+ constructor(name: string, properties?: Property[], components?: Component[]) {
16
12
  this.name = name
17
13
  if (properties) {
18
14
  this.properties = properties
@@ -40,7 +36,7 @@ export class Component {
40
36
  // Wrap lines
41
37
  while (line.length > MAX_LINE_LENGTH) {
42
38
  lines.push(line.substring(0, MAX_LINE_LENGTH))
43
- line = " " + line.substring(MAX_LINE_LENGTH)
39
+ line = ' ' + line.substring(MAX_LINE_LENGTH)
44
40
  }
45
41
  lines.push(line)
46
42
  }
@@ -80,6 +76,13 @@ export class Component {
80
76
  })
81
77
  }
82
78
 
79
+ removePropertiesWithName(name: string) {
80
+ const index = this.properties.findIndex(p => p.name === name)
81
+ if (index === -1) return
82
+ // Remove property at index
83
+ this.properties.splice(index, 1)
84
+ }
85
+
83
86
  getPropertyParams(name: string): string[] | null {
84
87
  for (const property of this.properties) {
85
88
  if (property.name === name) {
@@ -96,41 +99,355 @@ export class Component {
96
99
  }
97
100
  }
98
101
  }
102
+
103
+ addComponent(component: Component) {
104
+ this.components.push(component)
105
+ }
106
+
107
+ removeComponent(component: Component): boolean {
108
+ const index = this.components.indexOf(component)
109
+ if (index === -1) return false
110
+
111
+ // Remove element at index from list
112
+ this.components.splice(index, 1)
113
+
114
+ return true
115
+ }
116
+
117
+ getComponents(name: string): Component[] {
118
+ const components: Component[] = []
119
+
120
+ for (let component of this.components) {
121
+ if (component.name === name) {
122
+ components.push(component)
123
+ }
124
+ }
125
+
126
+ return components
127
+ }
99
128
  }
100
129
 
130
+ /**
131
+ * Represents a VCALENDAR component, the root component of an iCalendar file.
132
+ */
101
133
  export class Calendar extends Component {
102
134
  name = 'VCALENDAR'
103
135
 
104
- constructor(component: Component) {
136
+ /**
137
+ * @param prodid A unique identifier of the program creating the calendar.
138
+ *
139
+ * Example: `-//Google Inc//Google Calendar 70.9054//EN`
140
+ */
141
+ constructor(prodid: string)
142
+ /**
143
+ * @param prodid A unique identifier of the program creating the calendar.
144
+ *
145
+ * Example: `-//Google Inc//Google Calendar 70.9054//EN`
146
+ * @param version The version of the iCalendar specification that this calendar uses.
147
+ */
148
+ constructor(prodid: string, version: string)
149
+ /**
150
+ * @param component A VCALENDAR component.
151
+ */
152
+ constructor(component: Component)
153
+ constructor(a?: string | Component, b?: string) {
154
+ var component: Component
155
+ if (a instanceof Component) {
156
+ component = a as Component
157
+ } else {
158
+ const prodid = a as string
159
+ const version = (b as string) ?? '2.0'
160
+ component = new Component('VCALENDAR')
161
+ component.setProperty('PRODID', prodid)
162
+ component.setProperty('VERSION', version)
163
+ }
105
164
  super(component.name, component.properties, component.components)
106
165
  }
107
166
 
108
- events(): Array<CalendarEvent> {
109
- const events = new Array<CalendarEvent>()
167
+ events(): CalendarEvent[] {
168
+ return this.getComponents('VEVENT').map(c => new CalendarEvent(c))
169
+ }
110
170
 
111
- for (let component of this.components) {
112
- if (component.name === 'VEVENT') {
113
- events.push(new CalendarEvent(component))
171
+ removeEvent(event: CalendarEvent): boolean
172
+ removeEvent(uid: string): boolean
173
+ removeEvent(a: CalendarEvent | string): boolean {
174
+ if (a instanceof CalendarEvent) {
175
+ const event = a as CalendarEvent
176
+ return this.removeComponent(event)
177
+ } else {
178
+ const uid = a as string
179
+ for (const event of this.events()) {
180
+ if (event.uid() !== uid) continue
181
+ return this.removeComponent(event)
114
182
  }
115
183
  }
184
+ return false
185
+ }
186
+
187
+ prodId(): string {
188
+ return this.getProperty('PRODID')!.value
189
+ }
190
+
191
+ setProdId(value: string) {
192
+ this.setProperty('PRODID', value)
193
+ }
194
+
195
+ version(): string {
196
+ return this.getProperty('VERSION')!.value
197
+ }
198
+
199
+ setVersion(value: string) {
200
+ this.setProperty('VERSION', value)
201
+ }
202
+
203
+ calScale(): string | undefined {
204
+ return this.getProperty('CALSCALE')?.value
205
+ }
206
+
207
+ setCalScale(value: string) {
208
+ this.setProperty('CALSCALE', value)
209
+ }
210
+
211
+ removeCalScale() {
212
+ this.removePropertiesWithName('CALSCALE')
213
+ }
116
214
 
117
- return events
215
+ method(): string | undefined {
216
+ return this.getProperty('METHOD')?.value
217
+ }
218
+
219
+ setMethod(value: string) {
220
+ this.setProperty('METHOD', value)
221
+ }
222
+
223
+ removeMethod() {
224
+ this.removePropertiesWithName('METHOD')
225
+ }
226
+
227
+ calendarName(): string | undefined {
228
+ return this.getProperty('X-WR-CALNAME')?.value
229
+ }
230
+
231
+ setCalendarName(value: string) {
232
+ this.setProperty('X-WR-CALNAME', value)
233
+ }
234
+
235
+ removeCalendarName() {
236
+ this.removePropertiesWithName('X-WR-CALNAME')
237
+ }
238
+
239
+ calendarDescription(): string | undefined {
240
+ return this.getProperty('X-WR-CALDESC')?.value
241
+ }
242
+
243
+ setCalendarDescription(value: string) {
244
+ this.setProperty('X-WR-CALDESC', value)
245
+ }
246
+
247
+ removeCalendarDescription() {
248
+ this.removePropertiesWithName('X-WR-CALDESC')
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Represents a VTIMEZONE component, containing time zone definitions.
254
+ */
255
+ export class TimeZone extends Component {
256
+ constructor(id: string)
257
+ constructor(component: Component)
258
+ constructor(a: string | Component) {
259
+ var component: Component
260
+ if (a instanceof Component) {
261
+ component = a as Component
262
+ } else {
263
+ const tzid = a as string
264
+ component = new Component('VTIMEZONE')
265
+ component.setProperty('TZID', tzid)
266
+ }
267
+ super(component.name, component.properties, component.components)
268
+ }
269
+
270
+ id(): string {
271
+ return this.getProperty('TZID')!.value
272
+ }
273
+
274
+ setId(value: string) {
275
+ this.setProperty('TZID', value)
276
+ }
277
+
278
+ lastMod(): Date | undefined {
279
+ const text = this.getProperty('LAST-MOD')
280
+ if (!text) return
281
+ return new Date(text.value)
282
+ }
283
+
284
+ setLastMod(value: Date) {
285
+ this.setProperty('LAST-MOD', value.toISOString())
286
+ }
287
+
288
+ removeLastMod() {
289
+ this.removePropertiesWithName('LAST-MOD')
290
+ }
291
+
292
+ url(): string | undefined {
293
+ return this.getProperty('TZURL')?.value
294
+ }
295
+
296
+ setUrl(value: string) {
297
+ this.setProperty('TZURL', value)
298
+ }
299
+
300
+ removeUrl() {
301
+ this.removePropertiesWithName('TZURL')
302
+ }
303
+
304
+ /** Get all time offsets. */
305
+ offsets(): TimeZoneOffset[] {
306
+ const offsets: TimeZoneOffset[] = []
307
+ this.components.forEach(component => {
308
+ if (component.name === 'STANDARD' || component.name === 'DAYLIGHT') {
309
+ offsets.push(new TimeZoneOffset(component))
310
+ }
311
+ })
312
+ return offsets
313
+ }
314
+
315
+ /** Get standard/winter time offsets. */
316
+ standardOffsets(): TimeZoneOffset[] {
317
+ return this.getComponents('STANDARD').map(c => new TimeZoneOffset(c))
318
+ }
319
+
320
+ /** Get daylight savings time offsets. */
321
+ daylightOffsets(): TimeZoneOffset[] {
322
+ return this.getComponents('DAYLIGHT').map(c => new TimeZoneOffset(c))
323
+ }
324
+ }
325
+
326
+ export type OffsetType = 'DAYLIGHT' | 'STANDARD'
327
+ type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
328
+ export type Offset = `${'-' | '+'}${Digit}${Digit}${Digit}${Digit}`
329
+ /** Represents a STANDARD or DAYLIGHT component, defining a time zone offset. */
330
+ class TimeZoneOffset extends Component {
331
+ /**
332
+ *
333
+ * @param type If this is a STANDARD or DAYLIGHT component.
334
+ * @param start From when this offset is active.
335
+ * @param offsetFrom The offset that is in use prior to this time zone observance.
336
+ * @param offsetTo The offset that is in use during this time zone observance.
337
+ */
338
+ constructor(type: OffsetType, start: Date, offsetFrom: Offset, offsetTo: Offset)
339
+ constructor(component: Component)
340
+ constructor(a: OffsetType | Component, b?: Date, c?: Offset, d?: Offset) {
341
+ var component: Component
342
+ if (a instanceof Component) {
343
+ component = a as Component
344
+ } else {
345
+ const name = a as OffsetType
346
+ const start = b as Date
347
+ const offsetFrom = c as Offset
348
+ const offsetTo = d as Offset
349
+ component = new Component(name)
350
+ component.setProperty('DTSTART', start.toISOString())
351
+ component.setProperty('TZOFFSETFROM', offsetFrom)
352
+ component.setProperty('TZOFFSETTO', offsetTo)
353
+ }
354
+ super(component.name, component.properties, component.components)
355
+ }
356
+
357
+ start(): Date {
358
+ return new Date(this.getProperty('DTSTART')!.value)
359
+ }
360
+
361
+ setStart(value: Date) {
362
+ this.setProperty('DTSTART', value.toISOString())
363
+ }
364
+
365
+ offsetFrom(): Offset {
366
+ return this.getProperty('TZOFFSETFROM')!.value as Offset
367
+ }
368
+
369
+ setOffsetFrom(value: Offset) {
370
+ this.setProperty('TZOFFSETFROM', value)
371
+ }
372
+
373
+ offsetTo(): Offset {
374
+ return this.getProperty('TZOFFSETTO')!.value as Offset
375
+ }
376
+
377
+ setOffsetTo(value: Offset) {
378
+ this.setProperty('TZOFFSETTO', value)
379
+ }
380
+
381
+ comment(): string | undefined {
382
+ return this.getProperty('COMMENT')?.value
383
+ }
384
+
385
+ setComment(value: string) {
386
+ this.setProperty('COMMENT', value)
387
+ }
388
+
389
+ removeComment() {
390
+ this.removePropertiesWithName('COMMENT')
391
+ }
392
+
393
+ timeZoneName(): string | undefined {
394
+ return this.getProperty('TZNAME')?.value
395
+ }
396
+
397
+ setTimeZoneName(value: string) {
398
+ this.setProperty('TZNAME', value)
399
+ }
400
+
401
+ removeTimeZoneName() {
402
+ this.removePropertiesWithName('TZNAME')
118
403
  }
119
404
  }
120
405
 
121
406
  export class CalendarEvent extends Component {
122
407
  name = 'VEVENT'
123
408
 
124
- constructor(component: Component) {
409
+ constructor(uid: string, dtstamp: Date)
410
+ constructor(component: Component)
411
+ constructor(a: string | Component, b?: Date) {
412
+ var component: Component
413
+ if (b) {
414
+ const uid = a as string
415
+ const dtstamp = b as Date
416
+ component = new Component('VEVENT')
417
+ component.setProperty('UID', uid)
418
+ component.setProperty('DTSTAMP', dtstamp.toISOString())
419
+ } else {
420
+ component = a as Component
421
+ }
125
422
  super(component.name, component.properties, component.components)
126
423
  }
127
424
 
425
+ stamp(): Date {
426
+ return new Date(this.getProperty('DTSTAMP')!.value)
427
+ }
428
+
429
+ setStamp(value: Date) {
430
+ this.setProperty('DTSTAMP', value.toISOString())
431
+ }
432
+
433
+ uid(): string {
434
+ return this.getProperty('UID')!.value
435
+ }
436
+
437
+ setUid(value: string) {
438
+ this.setProperty('UID', value)
439
+ }
440
+
128
441
  summary(): string {
129
442
  return this.getProperty('SUMMARY')!.value
130
443
  }
131
444
 
132
445
  setSummary(value: string) {
133
- this.setProperty("SUMMARY", value)
446
+ this.setProperty('SUMMARY', value)
447
+ }
448
+
449
+ removeSummary() {
450
+ this.removePropertiesWithName('SUMMARY')
134
451
  }
135
452
 
136
453
  description(): string {
@@ -138,7 +455,11 @@ export class CalendarEvent extends Component {
138
455
  }
139
456
 
140
457
  setDescription(value: string) {
141
- this.setProperty("DESCRIPTION", value)
458
+ this.setProperty('DESCRIPTION', value)
459
+ }
460
+
461
+ removeDescription() {
462
+ this.removePropertiesWithName('DESCRIPTION')
142
463
  }
143
464
 
144
465
  location(): string | undefined {
@@ -146,7 +467,11 @@ export class CalendarEvent extends Component {
146
467
  }
147
468
 
148
469
  setLocation(value: string) {
149
- this.setProperty("LOCATION", value)
470
+ this.setProperty('LOCATION', value)
471
+ }
472
+
473
+ removeLocation() {
474
+ this.removePropertiesWithName('LOCATION')
150
475
  }
151
476
 
152
477
  start(): Date {
@@ -154,14 +479,49 @@ export class CalendarEvent extends Component {
154
479
  }
155
480
 
156
481
  setStart(value: Date) {
157
- this.setProperty("DTSTART", value.toISOString())
482
+ this.setProperty('DTSTART', value.toISOString())
483
+ }
484
+
485
+ removeStart() {
486
+ this.removePropertiesWithName('DTSTART')
158
487
  }
159
488
 
160
489
  end(): Date {
161
490
  return new Date(this.getProperty('DTEND')!.value)
162
491
  }
163
-
492
+
164
493
  setEnd(value: Date) {
165
- this.setProperty("DTEND", value.toISOString())
494
+ this.setProperty('DTEND', value.toISOString())
495
+ }
496
+
497
+ removeEnd() {
498
+ this.removePropertiesWithName('DTEND')
499
+ }
500
+
501
+ created(): Date | undefined {
502
+ const text = this.getProperty('CREATED')?.value
503
+ if (!text) return
504
+ return new Date(text)
505
+ }
506
+
507
+ setCreated(value: Date) {
508
+ this.setProperty('CREATED', value.toISOString())
509
+ }
510
+
511
+ removeCreated() {
512
+ this.removePropertiesWithName('CREATED')
513
+ }
514
+
515
+ geo(): [number, number] | undefined {
516
+ const text = this.getProperty('GEO')?.value
517
+ if (!text) return
518
+ const pattern = /^[+-]?\d+(\.\d+)?,[+-]?\d+(\.\d+)?$/
519
+ if (!pattern.test(text)) throw new Error(`Failed to parse GEO property: ${text}`)
520
+ const [longitude, latitude] = text.split(',')
521
+ return [parseFloat(longitude), parseFloat(latitude)]
522
+ }
523
+
524
+ setGeo(latitude: number, longitude: number) {
525
+ const text = `${latitude},${longitude}`
166
526
  }
167
527
  }
package/src/types.ts ADDED
@@ -0,0 +1,5 @@
1
+ export interface Property {
2
+ name: string
3
+ params: string[]
4
+ value: string
5
+ }