From 8ec2f441d40ab89b40cc3158f65c914eff497cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Mon, 4 Oct 2021 23:18:24 +0200 Subject: Major typescript work. --- static/vevent.ts | 268 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 146 insertions(+), 122 deletions(-) (limited to 'static/vevent.ts') diff --git a/static/vevent.ts b/static/vevent.ts index 678f2134..72ab28b1 100644 --- a/static/vevent.ts +++ b/static/vevent.ts @@ -1,46 +1,55 @@ "use strict"; +interface Redrawable extends HTMLElement { + redraw: ((data: VEvent) => void) +} + class VEventValue { - constructor (type, value, parameters = {}) { + + type: ical_type + value: any + parameters: Map + + constructor(type: ical_type, value: any, parameters = new Map()) { this.type = type; this.value = value; this.parameters = parameters; } - to_jcal () { + to_jcal(): [Map, ical_type, any] { let value; let v = this.value; switch (this.type) { - case 'binary': - /* TOOD */ - break; - case 'date-time': - value = v.format("~Y-~m-~dT~H:~M:~S"); - // TODO TZ - break; - case 'date': - value = v.format("~Y-~m-~d"); - break; - case 'duration': - /* TODO */ - break; - case 'period': - /* TODO */ - break; - case 'utc-offset': - /* TODO */ - break; - case 'recur': - value = v.asJcal(); - break; - - case 'float': - case 'integer': - case 'text': - case 'uri': - case 'cal-address': - case 'boolean': - value = v; + case 'binary': + /* TOOD */ + break; + case 'date-time': + value = v.format("~Y-~m-~dT~H:~M:~S"); + // TODO TZ + break; + case 'date': + value = v.format("~Y-~m-~d"); + break; + case 'duration': + /* TODO */ + break; + case 'period': + /* TODO */ + break; + case 'utc-offset': + /* TODO */ + break; + case 'recur': + value = v.asJcal(); + break; + + case 'float': + case 'integer': + case 'text': + case 'uri': + case 'cal-address': + case 'boolean': + value = v; } return [this.parameters, this.type, value]; } @@ -51,24 +60,38 @@ class VEventDuration extends VEventValue { } class VEvent { - constructor (properties = {}, components = []) { + + properties: Map + components: VEvent[] + registered: Redrawable[] + + constructor(properties: Map = new Map(), components: VEvent[] = []) { this.properties = properties; this.components = components; this.registered = []; } - getProperty (key) { - let e = this.properties[key]; - if (! e) return e; + getProperty(key: string): any | undefined { + let e = this.properties.get(key); + if (!e) return e; return e.value; } - setProperty (key, value) { - let e = this.properties[key]; - if (! e) { - let type = (valid_input_types[key.toUpperCase()] || ['unknown'])[0] - if (typeof type === typeof []) type = type[0]; - e = this.properties[key] = new VEventValue(type, value); + setProperty(key: string, value: any) { + let e = this.properties.get(key); + if (!e) { + key = key.toUpperCase() + let type: ical_type + let type_ = valid_input_types.get(key) + if (type_ === undefined) { + type = 'unknown' + } else if (type_ instanceof Array) { + type = type_[0] + } else { + type = type_ + } + e = new VEventValue(type, value) + this.properties.set(key, e); } else { e.value = value; } @@ -79,11 +102,11 @@ class VEvent { } } - register (htmlNode) { + register(htmlNode: Redrawable) { this.registered.push(htmlNode); } - to_jcal () { + to_jcal(): JCal { let out_properties = [] for (let [key, value] of Object.entries(this.properties)) { let sub = value.to_jcal(); @@ -94,118 +117,119 @@ class VEvent { } } -function make_vevent_value (value_tag) { +function make_vevent_value(value_tag: Element) { /* TODO parameters */ - return new VEventValue (value_tag.tagName, make_vevent_value_ (value_tag)); + return new VEventValue( + /* TODO error on invalid type? */ + value_tag.tagName as ical_type, + make_vevent_value_(value_tag)); } -function make_vevent_value_ (value_tag) { +function make_vevent_value_(value_tag: Element) { /* RFC6321 3.6. */ switch (value_tag.tagName) { - case 'binary': - /* Base64 to binary - Seems to handle inline whitespace, which xCal standard reqires - */ - return atob(value_tag.innerHTML) - break; - - case 'boolean': - switch (value_tag.innerHTML) { - case 'true': return true; - case 'false': return false; - default: - console.warn(`Bad boolean ${value_tag.innerHTML}, defaulting with !!`) - return !! value_tag.innerHTML; - } - break; - - case 'time': - case 'date': - case 'date-time': - return parseDate(value_tag.innerHTML); - break; - - case 'duration': - /* TODO duration parser here 'P1D' */ - return value_tag.innerHTML; - break; - - case 'float': - case 'integer': - return +value_tag.innerHTML; - break; - - case 'period': - /* TODO has sub components, meaning that a string wont do */ - let start = value_tag.getElementsByTagName('start')[0] - parseDate(start.innerHTML); - let other; - if ((other = value_tag.getElementsByTagName('end')[0])) { - return parseDate(other.innerHTML) - } else if ((other = value_tag.getElementsByTagName('duration')[0])) { - /* TODO parse duration */ - return other.innerHTML - } else { - console.warn('Invalid end to period, defaulting to 1H'); - return new Date(3600); - } + case 'binary': + /* Base64 to binary + Seems to handle inline whitespace, which xCal standard reqires + */ + return atob(value_tag.innerHTML) + + case 'boolean': + switch (value_tag.innerHTML) { + case 'true': return true; + case 'false': return false; + default: + console.warn(`Bad boolean ${value_tag.innerHTML}, defaulting with !!`) + return !!value_tag.innerHTML; + } + + case 'time': + case 'date': + case 'date-time': + return parseDate(value_tag.innerHTML); + + case 'duration': + /* TODO duration parser here 'P1D' */ + return value_tag.innerHTML; + + case 'float': + case 'integer': + return +value_tag.innerHTML; + + case 'period': + /* TODO has sub components, meaning that a string wont do */ + let start = value_tag.getElementsByTagName('start')[0] + parseDate(start.innerHTML); + let other; + if ((other = value_tag.getElementsByTagName('end')[0])) { + return parseDate(other.innerHTML) + } else if ((other = value_tag.getElementsByTagName('duration')[0])) { + /* TODO parse duration */ + return other.innerHTML + } else { + console.warn('Invalid end to period, defaulting to 1H'); + return new Date(3600); + } - case 'recur': - /* TODO parse */ - return ""; + case 'recur': + /* TODO parse */ + return ""; - case 'utc-offset': - /* TODO parse */ - return ""; + case 'utc-offset': + /* TODO parse */ + return ""; - default: - console.warn(`Unknown type '${value_tag.tagName}', defaulting to string`) - case 'cal-address': - case 'uri': - case 'text': - return value_tag.innerHTML; + default: + console.warn(`Unknown type '${value_tag.tagName}', defaulting to string`) + case 'cal-address': + case 'uri': + case 'text': + return value_tag.innerHTML; } } /* xml dom object -> class VEvent */ -function xml_to_vcal (xml) { +function xml_to_vcal(xml: Element): VEvent { /* xml MUST have a VEVENT (or equivalent) as its root */ let properties = xml.getElementsByTagName('properties')[0]; let components = xml.getElementsByTagName('components')[0]; - let property_map = {} + let property_map = new Map() if (properties) { for (var i = 0; i < properties.childElementCount; i++) { let tag = properties.childNodes[i]; + if (!(tag instanceof Element)) continue; let parameters = {}; - let value = []; + let value: VEventValue | VEventValue[] = []; for (var j = 0; j < tag.childElementCount; j++) { let child = tag.childNodes[j]; + if (!(child instanceof Element)) continue; switch (tag.tagName) { - case 'parameters': - parameters = /* handle parameters */ {}; - break; + case 'parameters': + parameters = /* TODO handle parameters */ {}; + break; /* These can contain multiple value tags, per RFC6321 3.4.1.1. */ - case 'categories': - case 'resources': - case 'freebusy': - case 'exdate': - case 'rdate': - value.push(make_vevent_value(child)); - break; - default: - value = make_vevent_value(child); + case 'categories': + case 'resources': + case 'freebusy': + case 'exdate': + case 'rdate': + (value as VEventValue[]).push(make_vevent_value(child)); + break; + default: + value = make_vevent_value(child); } } - property_map[tag.tagName] = value; + property_map.set(tag.tagName, value); } } let component_list = [] if (components) { for (let child of components.childNodes) { + if (!(child instanceof Element)) continue; component_list.push(xml_to_vcal(child)) } } -- cgit v1.2.3