Comparing version 0.6.5 to 0.7.0
@@ -146,2 +146,8 @@ // Copyright (C) 2011 Tri Tech Computers Ltd. | ||
// Replace an existing property or properties | ||
CalendarObject.prototype.setProperty = function(prop, value, parameters) { | ||
this.removeProperty(prop instanceof CalendarProperty ? prop.name : prop); | ||
this.addProperty(prop, value, parameters); | ||
} | ||
CalendarObject.prototype.addComponent = function(comp) { | ||
@@ -167,2 +173,6 @@ if(!(comp instanceof CalendarObject)) { | ||
CalendarObject.prototype.addComponents = function(comps) { | ||
comps.forEach(this.addComponent.bind(this)); | ||
} | ||
CalendarObject.prototype.getComponents = function(type) { | ||
@@ -192,2 +202,6 @@ if(type === undefined) { | ||
CalendarObject.prototype.removeProperty = function(prop) { | ||
delete this.properties[prop]; | ||
} | ||
CalendarObject.prototype.validate = function() { | ||
@@ -194,0 +208,0 @@ var self = this; |
@@ -36,3 +36,3 @@ "use strict"; | ||
var VEvent = exports.VEvent = function(calendar, uid) { | ||
if(!(calendar instanceof iCalendar)) { | ||
if(!(calendar instanceof iCalendar) && calendar != null) { | ||
uid = calendar; | ||
@@ -58,2 +58,6 @@ calendar = null; | ||
VEvent.prototype.setLocation = function(loc) { | ||
this.addProperty('LOCATION', loc); | ||
} | ||
VEvent.prototype.setDescription = function(desc) { | ||
@@ -111,3 +115,35 @@ this.addProperty('DESCRIPTION', desc); | ||
// Respond to this invitation (assumes this is an invitation) | ||
// | ||
// fromuser: URL for the user, usually in the form mailto:bob@example.com | ||
// status: true, false, 'ACCEPTED', 'DECLINED', 'TENTATIVE', or as per RFC5545 | ||
VEvent.prototype.reply = function(fromuser, status) { | ||
var resp = this.clone(true); | ||
if(status === true || status === undefined) | ||
status = 'ACCEPTED'; | ||
else if(status === false) | ||
status = 'DECLINED'; | ||
resp.setProperty('ATTENDEE', fromuser, { | ||
'PARTSTAT': status | ||
}); | ||
resp.setProperty('DTSTAMP', new Date()); | ||
resp.setProperty('LAST-MODIFIED', new Date()); | ||
var ics = new iCalendar(); | ||
// TODO: Support REFRESH/COUNTER | ||
ics.addProperty('METHOD', 'REPLY'); | ||
// Copy VTIMEZONE components... | ||
if(this.calendar) | ||
ics.addComponents(this.calendar.getComponents('VTIMEZONE')); | ||
ics.addComponent(resp); | ||
return ics; | ||
} | ||
schema.VEVENT = { | ||
@@ -114,0 +150,0 @@ factory: VEvent, |
@@ -171,3 +171,3 @@ // Copyright (C) 2011 Tri Tech Computers Ltd. | ||
after = new Date(this.start.valueOf() - 1); | ||
if(this.end && after > this.end) return null; | ||
if(this.until && after > this.until) return null; | ||
@@ -187,4 +187,4 @@ var freq = FREQ[this.rule.FREQ]; | ||
if((exdate.valueOf() == nextInLocal.valueOf()) | ||
|| (exdate.date_only && y(exdate) == y(nextInLocal) | ||
&& m(exdate) == m(nextInLocal) && d(exdate) == d(nextInLocal))) { | ||
|| (exdate.date_only && y(to_utc_date(exdate)) == y(nextInLocal) | ||
&& m(to_utc_date(exdate)) == m(nextInLocal) && d(to_utc_date(exdate)) == d(nextInLocal))) { | ||
after = next; | ||
@@ -199,3 +199,3 @@ continue NextOccurs; | ||
// Date is off the end of the spectrum... | ||
if(this.end && next > this.end) | ||
if(this.until && next > this.until) | ||
return null; | ||
@@ -210,7 +210,7 @@ | ||
if(next > this.count_end) | ||
if(next > to_utc_date(this.count_end)) | ||
return null; | ||
} | ||
if(this.rule.UNTIL && next > this.rule.UNTIL) | ||
if(this.rule.UNTIL && next > to_utc_date(this.rule.UNTIL)) | ||
return null; | ||
@@ -217,0 +217,0 @@ |
@@ -174,3 +174,3 @@ // Copyright (C) 2011 Tri Tech Computers Ltd. | ||
format: function(value) { | ||
return value.toString().replace(/([\\,;])/g, "\\$1").replace(/\n/g, "\\n"); | ||
return (value || '').toString().replace(/([\\,;])/g, "\\$1").replace(/\n/g, "\\n"); | ||
}, | ||
@@ -243,3 +243,7 @@ parse: function(value) { | ||
return fmt.parse ? fmt.parse(value, parameters || {}, calendar) : value; | ||
// Handle wrong value type | ||
parameters = parameters || {}; | ||
var otherFmt = parameters.VALUE && _types[parameters.VALUE]; | ||
if (otherFmt) fmt = otherFmt; | ||
return fmt.parse ? fmt.parse(value, parameters, calendar) : value; | ||
} |
{ | ||
"name": "icalendar", | ||
"version": "0.6.5", | ||
"version": "0.7.0", | ||
"author": "James Emerton <james@tri-tech.com>", | ||
@@ -15,3 +15,5 @@ "description": "RFC5545 iCalendar parser/generator", | ||
"devDependencies": { | ||
"jasmine-node": ">=1.0.13" | ||
"grunt": "~0.4.1", | ||
"grunt-jasmine-node": "~0.2.1", | ||
"jasmine-node": "~1.14.5" | ||
}, | ||
@@ -18,0 +20,0 @@ "repository": { |
@@ -238,3 +238,20 @@ // Test search | ||
}); | ||
it('parses DateTime Trigger correctly', function () { | ||
var cal = parse_calendar( | ||
'BEGIN:VCALENDAR\r\n'+ | ||
'PRODID:-//Bobs Software Emporium//NONSGML Bobs Calendar//EN\r\n'+ | ||
'VERSION:2.0\r\n'+ | ||
'BEGIN:VEVENT\r\n'+ | ||
'DTSTAMP:20111202T165900\r\n'+ | ||
'TRIGGER;VALUE=DATE-TIME:20111109T173216\r\n'+ | ||
'UID:testuid@someotherplace.com\r\n'+ | ||
'END:VEVENT\r\n'+ | ||
'END:VCALENDAR\r\n'); | ||
var vevent = cal.getComponents('VEVENT')[0]; | ||
expect(new Date(2011,10,9,17,32,16)).toEqual(vevent.getPropertyValue('TRIGGER')); | ||
}); | ||
}); | ||
@@ -61,2 +61,42 @@ | ||
it("finds recurrences in a specific timeframe, ignoring `dtend`", function() { | ||
var rrule = new RRule( | ||
'FREQ=MONTHLY;BYDAY=3MO', | ||
new Date(2013,2,18,9), | ||
new Date(2013,2,18,10) | ||
); | ||
expect(rrule.nextOccurences(new Date(2013,9,1), new Date(2013,11,1))) | ||
.toEqual([ | ||
new Date(2013,9,21,9), | ||
new Date(2013,10,18,9) | ||
]); | ||
}); | ||
it("finds recurrences in a specific timeframe, honoring `until`", function() { | ||
var rrule = new RRule( | ||
'FREQ=MONTHLY;BYDAY=3MO;UNTIL=20131101', | ||
new Date(2013,2,18,9), | ||
new Date(2013,2,18,10) | ||
); | ||
expect(rrule.nextOccurences(new Date(2013,9,1), new Date(2013,11,1))) | ||
.toEqual([ | ||
new Date(2013,9,21,9), | ||
]); | ||
}); | ||
it("finds recurrences in a specific timeframe, honoring `until` (inclusive)", function() { | ||
var rrule = new RRule( | ||
'FREQ=MONTHLY;BYDAY=3MO;UNTIL=20130318', | ||
new Date(2013,2,18), | ||
new Date(2013,2,18) | ||
); | ||
expect(rrule.nextOccurences(new Date(2013,2,1), new Date(2013,2,20))) | ||
.toEqual([ | ||
new Date(2013,2,18), | ||
]); | ||
}); | ||
it("respects EXDATE date_only parts", function() { | ||
@@ -63,0 +103,0 @@ var rrule = new RRule('FREQ=MONTHLY', { |
@@ -130,3 +130,83 @@ | ||
}); | ||
it('can reply to invitations', function() { | ||
var cal = icalendar.parse_calendar( | ||
'BEGIN:VCALENDAR\r\n'+ | ||
'METHOD:REQUEST\r\n'+ | ||
'PRODID:Microsoft Exchange Server 2010\r\n'+ | ||
'VERSION:2.0\r\n'+ | ||
'BEGIN:VEVENT\r\n'+ | ||
'ORGANIZER;CN=Bob Smith:MAILTO:bob@example.com\r\n'+ | ||
'ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=jim@exampl\r\n'+ | ||
' e.com:MAILTO:jim@example.com\r\n'+ | ||
'SUMMARY;LANGUAGE=en-US:Dentist Appointment\r\n'+ | ||
'DTSTART:20140903T133000\r\n'+ | ||
'DTEND:20140903T140000\r\n'+ | ||
'UID:38F2C174-A263-481A-987C-75392FF42AF6\r\n'+ | ||
'DTSTAMP:20140902T181530Z\r\n'+ | ||
'TRANSP:OPAQUE\r\n'+ | ||
'STATUS:CONFIRMED\r\n'+ | ||
'SEQUENCE:2\r\n'+ | ||
'END:VEVENT\r\n'+ | ||
'END:VCALENDAR\r\n'); | ||
var resp = cal.events()[0].reply('mailto:jim@example.com'); | ||
expect(resp.getPropertyValue('METHOD')).toEqual('REPLY'); | ||
// UID and SEQUENCE must remain the same... | ||
expect(resp.events()[0].getPropertyValue('UID')) | ||
.toEqual('38F2C174-A263-481A-987C-75392FF42AF6'); | ||
expect(resp.events()[0].getPropertyValue('SEQUENCE')).toEqual('2'); | ||
var attendee = resp.events()[0].getProperty('ATTENDEE'); | ||
expect(attendee.value).toEqual('mailto:jim@example.com'); | ||
expect(attendee.getParameter('PARTSTAT')).toEqual('ACCEPTED'); | ||
}); | ||
it('copies timezone data when responding to invitations', function() { | ||
var cal = icalendar.parse_calendar( | ||
'BEGIN:VCALENDAR\r\n'+ | ||
'METHOD:REQUEST\r\n'+ | ||
'PRODID:Microsoft Exchange Server 2010\r\n'+ | ||
'VERSION:2.0\r\n'+ | ||
'BEGIN:VTIMEZONE\r\n'+ | ||
'TZID:Eastern Standard Time\r\n'+ | ||
'BEGIN:STANDARD\r\n'+ | ||
'DTSTART:16010101T020000\r\n'+ | ||
'TZOFFSETFROM:-0400\r\n'+ | ||
'TZOFFSETTO:-0500\r\n'+ | ||
'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11\r\n'+ | ||
'END:STANDARD\r\n'+ | ||
'BEGIN:DAYLIGHT\r\n'+ | ||
'DTSTART:16010101T020000\r\n'+ | ||
'TZOFFSETFROM:-0500\r\n'+ | ||
'TZOFFSETTO:-0400\r\n'+ | ||
'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3\r\n'+ | ||
'END:DAYLIGHT\r\n'+ | ||
'END:VTIMEZONE\r\n'+ | ||
'BEGIN:VEVENT\r\n'+ | ||
'ORGANIZER;CN=Bob Smith:MAILTO:bob@example.com\r\n'+ | ||
'ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=jim@exampl\r\n'+ | ||
' e.com:MAILTO:jim@example.com\r\n'+ | ||
'SUMMARY;LANGUAGE=en-US:Dentist Appointment\r\n'+ | ||
'DTSTART:20140903T133000\r\n'+ | ||
'DTEND:20140903T140000\r\n'+ | ||
'UID:38F2C174-A263-481A-987C-75392FF42AF6\r\n'+ | ||
'DTSTAMP:20140902T181530Z\r\n'+ | ||
'TRANSP:OPAQUE\r\n'+ | ||
'STATUS:CONFIRMED\r\n'+ | ||
'SEQUENCE:2\r\n'+ | ||
'END:VEVENT\r\n'+ | ||
'END:VCALENDAR\r\n'); | ||
var resp = cal.events()[0].reply('mailto:jim@example.com'); | ||
expect(resp.getComponents('VTIMEZONE').length).toEqual(1); | ||
var tz = resp.getComponents('VTIMEZONE')[0]; | ||
expect(tz.getPropertyValue('TZID')).toEqual('Eastern Standard Time'); | ||
expect(tz.getComponents('STANDARD')[0].getPropertyValue('TZOFFSETFROM')) | ||
.toEqual('-0400'); | ||
}); | ||
}); | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
190171
25
2332
3
3