1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
export {
ical_type,
valid_input_types,
JCalProperty, JCal
}
let all_types = [
'text',
'uri',
'binary',
'float', /* Number.type = 'float' */
'integer', /* Number.type = 'integer' */
'date-time', /* Date */
'date', /* Date.dateonly = true */
'duration',
'period',
'utc-offset',
'cal-address',
'recur', /* RRule */
'boolean', /* boolean */
]
type ical_type
= 'text'
| 'uri'
| 'binary'
| 'float'
| 'integer'
| 'date-time'
| 'date'
| 'duration'
| 'period'
| 'utc-offset'
| 'cal-address'
| 'recur'
| 'boolean'
| 'unknown'
let property_names = [
'calscale', 'method', 'prodid', 'version', 'attach', 'categories',
'class', 'comment', 'description', 'geo', 'location', 'percent-complete',
'priority', 'resources', 'status', 'summary', 'completed', 'dtend', 'due',
'dtstart', 'duration', 'freebusy', 'transp', 'tzid', 'tzname', 'tzoffsetfrom',
'tzoffsetto', 'tzurl', 'attendee', 'contact', 'organizer', 'recurrence-id',
'related-to', 'url', 'uid', 'exdate', 'exrule', 'rdate', 'rrule', 'action',
'repeat', 'trigger', 'created', 'dtstamp', 'last-modified', 'sequence', 'request-status'
];
let valid_fields: Map<string, string[]> = new Map([
['VCALENDAR', ['PRODID', 'VERSION', 'CALSCALE', 'METHOD']],
['VEVENT', ['DTSTAMP', 'UID', 'DTSTART', 'CLASS', 'CREATED',
'DESCRIPTION', 'GEO', 'LAST-MODIFIED', 'LOCATION',
'ORGANIZER', 'PRIORITY', 'SEQUENCE', 'STATUS',
'SUMMARY', 'TRANSP', 'URL', 'RECURRENCE-ID',
'RRULE', 'DTEND', 'DURATION', 'ATTACH', 'ATTENDEE',
'CATEGORIES', 'COMMENT', 'CONTACT', 'EXDATE',
'REQUEST-STATUS', 'RELATED-TO', 'RESOURCES', 'RDATE']],
['VTODO', ['DTSTAMP', 'UID', 'CLASS', 'COMPLETED', 'CREATED',
'DESCRIPTION', 'DTSTART', 'GEO', 'LAST-MODIFIED',
'LOCATION', 'ORGANIZER', 'PERCENT-COMPLETE', 'PRIORITY',
'RECURRENCE-ID', 'SEQUENCE', 'STATUS', 'SUMMARY', 'URL',
'RRULE', 'DUE', 'DURATION', 'ATTACH', 'ATTENDEE', 'CATEGORIES',
'COMMENT', 'CONTACT', 'EXDATE', 'REQUEST-STATUS', 'RELATED-TO',
'RESOURCES', 'RDATE',]],
['VJOURNAL', ['DTSTAMP', 'UID', 'CLASS', 'CREATED', 'DTSTART', 'LAST-MODIFIED',
'ORGANIZER', 'RECURRENCE-ID', 'SEQUENCE', 'STATUS', 'SUMMARY',
'URL', 'RRULE', 'ATTACH', 'ATTENDEE', 'CATEGORIES', 'COMMENT',
'CONTACT', 'DESCRIPTION', 'EXDATE', 'RELATED-TO', 'RDATE',
'REQUEST-STATUS']],
['VFREEBUSY', ['DTSTAMP', 'UID', 'CONTACT', 'DTSTART', 'DTEND',
'ORGANIZER', 'URL', 'ATTENDEE', 'COMMENT', 'FREEBUSY',
'REQUEST-STATUS']],
['VTIMEZONE', ['TZID', 'LAST-MODIFIED', 'TZURL']],
['VALARM', ['ACTION', 'TRIGGER', 'DURATION', 'REPEAT', 'ATTACH',
'DESCRIPTION', 'SUMMARY', 'ATTENDEE']],
['STANDARD', ['DTSTART', 'TZOFFSETFROM', 'TZOFFSETTO', 'RRULE',
'COMMENT', 'RDATE', 'TZNAME']],
])
valid_fields.set('DAYLIGHT', valid_fields.get('STANDARD')!);
type known_ical_types
= 'ACTION'
| 'ATTACH'
| 'ATTENDEE'
| 'CALSCALE'
| 'CATEGORIES'
| 'CLASS'
| 'COMMENT'
| 'COMPLETED'
| 'CONTACT'
| 'CREATED'
| 'DESCRIPTION'
| 'DTEND'
| 'DTSTAMP'
| 'DTSTART'
| 'DUE'
| 'DURATION'
| 'EXDATE'
| 'FREEBUSY'
| 'GEO'
| 'LAST-MODIFIED'
| 'LOCATION'
| 'METHOD'
| 'ORGANIZER'
| 'PERCENT-COMPLETE'
| 'PRIORITY'
| 'PRODID'
| 'RDATE'
| 'RECURRENCE-ID'
| 'RELATED-TO'
| 'REPEAT'
| 'REQUEST-STATUS'
| 'RESOURCES'
| 'RRULE'
| 'SEQUENCE'
| 'STATUS'
| 'SUMMARY'
| 'TRANSP'
| 'TRIGGER'
| 'TZID'
| 'TZNAME'
| 'TZOFFSETFROM'
| 'TZOFFSETTO'
| 'TZURL'
| 'URL'
| 'VERSION'
let valid_input_types: Map<string, ical_type | ical_type[]> =
new Map([
['ACTION', ['text']], // AUDIO|DISPLAY|EMAIL|*other*
['ATTACH', ['uri', 'binary']],
['ATTENDEE', ['cal-address']],
['CALSCALE', ['text']],
['CATEGORIES', [['text']]],
['CLASS', ['text']], // PUBLIC|PRIVATE|CONFIDENTIAL|*other*
['COMMENT', ['text']],
['COMPLETED', ['date-time']],
['CONTACT', ['text']],
['CREATED', ['date-time']],
['DESCRIPTION', ['text']],
['DTEND', ['date', 'date-time']],
['DTSTAMP', ['date-time']],
['DTSTART', ['date', 'date-time']],
['DUE', ['date', 'date-time']],
['DURATION', ['duration']],
['EXDATE', [['date', 'date-time']]],
['FREEBUSY', [['period']]],
['GEO', ['float']], // pair of floats
['LAST-MODIFIED', ['date-time']],
['LOCATION', ['text']],
['METHOD', ['text']],
['ORGANIZER', ['cal-address']],
['PERCENT-COMPLETE', ['integer']], // 0-100
['PRIORITY', ['integer']], // 0-9
['PRODID', ['text']],
['RDATE', [['date', 'date-time', 'period']]],
['RECURRENCE-ID', ['date', 'date-time']],
['RELATED-TO', ['text']],
['REPEAT', ['integer']],
['REQUEST-STATUS', ['text']],
['RESOURCES', [['text']]],
['RRULE', ['recur']],
['SEQUENCE', ['integer']],
['STATUS', ['text']], // see 3.8.1.11
['SUMMARY', ['text']],
['TRANSP', ['text']], // OPAQUE|TRANSPARENT
['TRIGGER', ['duration', 'date-time']],
['TZID', ['text']],
['TZNAME', ['text']],
['TZOFFSETFROM', ['utc-offset']],
['TZOFFSETTO', ['utc-offset']],
['TZURL', ['uri']],
['URL', ['uri']],
['VERSION', ['text']],
]) as Map<string, ical_type | ical_type[]>
// type JCalLine {
// }
type tagname = 'vevent' | string
type JCalProperty = [string, any, ical_type, any[]]
type JCal = [tagname, JCalProperty[], JCal[]]
|