custom tags
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
function parseICal(content: string): Array<{
|
||||
title: string;
|
||||
description?: string;
|
||||
start: Date;
|
||||
end?: Date;
|
||||
allDay?: boolean;
|
||||
rrule?: string;
|
||||
uid?: string;
|
||||
priority?: number;
|
||||
}> {
|
||||
const events: Array<{
|
||||
title: string;
|
||||
description?: string;
|
||||
start: Date;
|
||||
end?: Date;
|
||||
allDay?: boolean;
|
||||
rrule?: string;
|
||||
uid?: string;
|
||||
priority?: number;
|
||||
}> = [];
|
||||
|
||||
const lines = content.split('\n');
|
||||
let i = 0;
|
||||
|
||||
while (i < lines.length) {
|
||||
const line = lines[i].trim();
|
||||
if (!line) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith('BEGIN:VEVENT')) {
|
||||
const event: {
|
||||
title: string;
|
||||
description?: string;
|
||||
start: Date;
|
||||
end?: Date;
|
||||
allDay?: boolean;
|
||||
rrule?: string;
|
||||
uid?: string;
|
||||
priority?: number;
|
||||
} = {
|
||||
title: '',
|
||||
start: new Date(0),
|
||||
};
|
||||
|
||||
i++;
|
||||
let inEvent = true;
|
||||
|
||||
while (i < lines.length && inEvent) {
|
||||
const line = lines[i].trim();
|
||||
i++;
|
||||
|
||||
if (line === 'END:VEVENT') {
|
||||
inEvent = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith('END:')) {
|
||||
inEvent = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith('SUMMARY:')) {
|
||||
event.title = line.substring(8).trim();
|
||||
} else if (line.startsWith('DESCRIPTION:')) {
|
||||
event.description = line.substring(12).trim();
|
||||
} else if (line.startsWith('DTSTART:')) {
|
||||
const dateStr = line.substring(8).trim();
|
||||
event.start = parseICalDateTime(dateStr);
|
||||
} else if (line.startsWith('DTEND:')) {
|
||||
const dateStr = line.substring(6).trim();
|
||||
event.end = parseICalDateTime(dateStr);
|
||||
} else if (line.startsWith('DTSTAMP:')) {
|
||||
// ignore, we use start date
|
||||
} else if (line.startsWith('UID:')) {
|
||||
event.uid = line.substring(4).trim();
|
||||
} else if (line.startsWith('PRIORITY:')) {
|
||||
event.priority = parseInt(line.substring(9).trim(), 10);
|
||||
} else if (line.startsWith('ALL-DAY:')) {
|
||||
event.allDay = line.substring(10).trim().toLowerCase() === 'true';
|
||||
} else if (line.startsWith('RRULE:')) {
|
||||
event.rrule = line.substring(6).trim();
|
||||
} else if (line.startsWith('BEGIN:VALARM')) {
|
||||
// skip alarms
|
||||
i++;
|
||||
let inAlarm = true;
|
||||
while (i < lines.length && inAlarm) {
|
||||
const alarmLine = lines[i].trim();
|
||||
i++;
|
||||
if (alarmLine === 'END:VALARM') {
|
||||
inAlarm = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// skip unrecognized lines
|
||||
}
|
||||
}
|
||||
|
||||
if (event.title) {
|
||||
events.push(event);
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
function parseICalDateTime(dateStr: string): Date {
|
||||
// Handle various iCal date/time formats
|
||||
// Format 1: YYYYMMDDTHHMMSSZ (UTC)
|
||||
// Format 2: YYYYMMDDTHHMMSS (local)
|
||||
// Format 3: YYYYMMDD (date only)
|
||||
// Format 4: TZID:... (with timezone)
|
||||
|
||||
let datePart = '';
|
||||
let timePart = '';
|
||||
let hasTime = false;
|
||||
|
||||
// Check for Z (UTC) indicator
|
||||
const hasZ = dateStr.endsWith('Z');
|
||||
const cleanStr = hasZ ? dateStr.slice(0, -1) : dateStr;
|
||||
|
||||
// Try to split at T
|
||||
const tIndex = cleanStr.indexOf('T');
|
||||
if (tIndex !== -1) {
|
||||
datePart = cleanStr.substring(0, tIndex);
|
||||
timePart = cleanStr.substring(tIndex + 1);
|
||||
hasTime = true;
|
||||
} else {
|
||||
datePart = cleanStr;
|
||||
}
|
||||
|
||||
// Parse date (YYYYMMDD)
|
||||
if (datePart.length >= 8) {
|
||||
const year = parseInt(datePart.substring(0, 4), 10);
|
||||
const month = parseInt(datePart.substring(4, 6), 10) - 1; // 0-indexed
|
||||
const day = parseInt(datePart.substring(6, 8), 10);
|
||||
const date = new Date(year, month, day);
|
||||
|
||||
if (hasTime && timePart) {
|
||||
const hour = parseInt(timePart.substring(0, 2), 10);
|
||||
const minute = parseInt(timePart.substring(2, 4), 10);
|
||||
date.setHours(hour, minute, 0, 0);
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
// Fallback: try Date.parse
|
||||
return new Date(dateStr);
|
||||
}
|
||||
|
||||
export default parseICal;
|
||||
Reference in New Issue
Block a user