Skip to content

Instantly share code, notes, and snippets.

@bartoszbobin
Created April 10, 2018 21:03
Show Gist options
  • Save bartoszbobin/533a9ef36166eb3c4ad389bfd3602204 to your computer and use it in GitHub Desktop.
Save bartoszbobin/533a9ef36166eb3c4ad389bfd3602204 to your computer and use it in GitHub Desktop.
Simple ICalendar Parser to JS Objects
/**
* @copyright bartosz.bobin
*/
export class ICalendarParser {
skipNotStandardKeys = true;
parse(text: string) {
const lines = text.replace(/\n /g, '').split(/\n/);
let obj = {vcalendar: undefined};
this.analyseCalendar(lines, obj);
return obj.vcalendar;
}
private analyseCalendar(lines, obj) {
const path = [obj];
for (let line of lines) {
line = line.trim();
let currentPathItem = path[path.length - 1];
if (line.indexOf('BEGIN:') === 0) {
this.createNewPathItem(line, currentPathItem, path);
continue;
}
if (line.indexOf(`END:`) === 0) {
path.pop();
continue;
}
if (line.indexOf(`X-`) === 0 && this.skipNotStandardKeys) {
continue;
}
this.analyseProperty(line, currentPathItem);
}
}
private analyseProperty(line, current) {
const keyValueSeparatorIndex = line.indexOf(':');
let key = line.substr(0, keyValueSeparatorIndex);
const keyPropertySeparatorIndex = key.indexOf(';');
let value = {
data: line.substr(keyValueSeparatorIndex + 1)
};
if (keyPropertySeparatorIndex > -1) {
const properties = key.split(/;/g);
key = properties.shift();
for (const prop of properties) {
const t = prop.split('=');
value[ICalendarParser.toCamelCase(t.shift())] = t.join('=');
}
}
current[ICalendarParser.toCamelCase(key)] = value;
}
private createNewPathItem(line, currentPathItem, path) {
const keyName = ICalendarParser.toCamelCase(line.substr(6));
const item = this.keyToObjectMapper(keyName);
if (typeof currentPathItem[keyName] === 'object') {
if (!Array.isArray(currentPathItem[keyName])) {
currentPathItem[keyName] = [currentPathItem[keyName]];
}
currentPathItem[keyName].push(item);
} else {
currentPathItem[keyName] = item;
}
path.push(item);
}
private keyToObjectMapper(key) {
switch (key.toLowerCase()) {
case "vcalendar": return new VCalendar();
case "vevent": return new VEvent();
case "vtodo": return new VTodo();
case "vjournal": return new VJournal();
case "vfreebusy": return new VFreeBusy();
case "vtimezone": return new VTimezone();
default:return {};
}
}
static toCamelCase(str) {
return str.toLowerCase();
}
}
export class VCalendar {}
export class VEvent {}
export class VTodo {}
export class VJournal {}
export class VFreeBusy {}
export class VTimezone {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment