Comparing version 0.2.0 to 0.3.0
@@ -52,5 +52,29 @@ // Copyright (C) 2011 Tri Tech Computers Ltd. | ||
// Create an element of the correct type | ||
CalendarObject.create = function(element, calendar) { | ||
var factory = (schema[element] || {}).factory; | ||
return (factory !== undefined | ||
? new factory(calendar) | ||
: new CalendarObject(calendar, comp)); | ||
} | ||
// Recursively generates a clone of some calendar object | ||
CalendarObject.prototype.clone = function() { | ||
var obj = CalendarObject.create(this.element, this.calendar); | ||
for(var prop in this.properties) | ||
obj.addProperty(this.properties[prop]); | ||
var comp = this.getComponents(); | ||
for(var i=0; i<comp.length; ++i) | ||
obj.addComponent(comp[i]); | ||
return obj; | ||
} | ||
CalendarObject.prototype.addProperty = function(prop, value, parameters) { | ||
if(!(prop instanceof CalendarProperty)) | ||
prop = new CalendarProperty(prop, value, parameters); | ||
else | ||
prop = prop.clone(); | ||
@@ -70,2 +94,8 @@ // TODO: What about multiple occurances of the same property? | ||
// Create a copy of the component if it's from a different | ||
// calendar object to prevent changes from one place happening | ||
// somewhere else as well | ||
if(comp.calendar && comp.calendar !== this.calendar) | ||
comp = comp.clone(); | ||
this.components[comp.element] = this.components[comp.element] || []; | ||
@@ -139,2 +169,13 @@ this.components[comp.element].push(comp); | ||
CalendarProperty.prototype.clone = function() { | ||
var obj = new CalendarProperty(this.name, this.value); | ||
obj.type = this.type; | ||
// TODO: Copy type and value instances in the case of objects, dates, arrays | ||
for(var param in this.parameters) | ||
obj.parameters[param] = this.parameters[param]; | ||
return obj; | ||
} | ||
CalendarProperty.prototype.getParameter = function(param) { | ||
@@ -294,2 +335,3 @@ return this.parameters[param]; | ||
VCALENDAR: { | ||
factory: iCalendar, | ||
valid_properties: [], | ||
@@ -296,0 +338,0 @@ required_properties: ['PRODID','VERSION'], |
@@ -42,6 +42,6 @@ // Copyright (C) 2011 Tri Tech Computers Ltd. | ||
if(element != expect_element) | ||
throw ParseError("Expected "+expect_element+" got "+element); | ||
throw new ParseError("Expected "+expect_element+" got "+element); | ||
if(expect_value && expect_value != value) | ||
throw ParseError("Expected "+expect_value+" got "+value); | ||
throw new ParseError("Expected "+expect_value+" got "+value); | ||
@@ -83,6 +83,21 @@ return next_state; | ||
exports.parse_calendar = function(data) { | ||
// Parse iCalendar formatted data and return an iCalendar object | ||
// | ||
// The second argument is an optional calendar object containing VTIMEZONE | ||
// data to aid in the correct conversion of dates | ||
exports.parse_calendar = function(data, timezone) { | ||
data = data.split(/\r?\n/); | ||
var calendar = new ics.iCalendar(true); | ||
if(timezone) { | ||
if(typeof timezone === 'string') | ||
timezone = exports.parse_calendar(timezone); | ||
if(timezone instanceof ics.iCalendar) { | ||
var tzs = timezone.getComponents('VTIMEZONE'); | ||
for(var i=0; i<tzs.length; ++i) | ||
calendar.addComponent(tzs[i]); | ||
} | ||
else | ||
calendar.addComponent(tzs[i]); | ||
} | ||
var state = expect("BEGIN", "VCALENDAR", parse_component(calendar)); | ||
@@ -119,3 +134,3 @@ | ||
if(state === undefined) | ||
throw ParseError("Mismatched BEGIN/END tags"); | ||
throw new ParseError("Mismatched BEGIN/END tags"); | ||
@@ -126,5 +141,5 @@ state = state(propname, element[2], parameters); | ||
if(state !== undefined) | ||
throw ParseError("Unable to parse calendar data; END:VCALENDAR not found!"); | ||
throw new ParseError("Unable to parse calendar data; END:VCALENDAR not found!"); | ||
return calendar; | ||
} |
{ | ||
"name": "icalendar", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"author": "James Emerton <james@tri-tech.com>", | ||
@@ -5,0 +5,0 @@ "description": "RFC5545 iCalendar parser/generator", |
@@ -11,65 +11,2 @@ // Test search | ||
describe("iCalendar", function() { | ||
it('formats icalendar data types', function() { | ||
assert.equal('AAECBAUG', icalendar.format_value('BINARY', | ||
new Buffer('\u0000\u0001\u0002\u0004\u0005\u0006'))); | ||
var dt = new Date(2011,10,9,17,32,16); | ||
var dt2 = new Date(2011,10,10,19,32); | ||
assert.equal('20111109', icalendar.format_value('DATE', dt)); | ||
assert.equal('173216', icalendar.format_value('TIME', dt)); | ||
assert.equal('20111109T173216', icalendar.format_value('DATE-TIME', dt)); | ||
assert.equal('P1W', icalendar.format_value('DURATION', 60*60*24*7)); | ||
assert.equal('P1D', icalendar.format_value('DURATION', 60*60*24)); | ||
assert.equal('PT1H', icalendar.format_value('DURATION', 60*60)); | ||
assert.equal('PT1M', icalendar.format_value('DURATION', 60)); | ||
assert.equal('PT1S', icalendar.format_value('DURATION', 1)); | ||
assert.equal('P1W2DT3H4M5S', icalendar.format_value('DURATION', | ||
60*60*24*7 + 60*60*24*2 + 60*60*3 + 60*4 + 5)); | ||
assert.equal('1.333', icalendar.format_value('FLOAT', 1.333)); | ||
assert.equal('-3.14', icalendar.format_value('FLOAT', -3.14)); | ||
assert.equal('1234567890', icalendar.format_value('INTEGER', 1234567890)); | ||
assert.equal('20111109T173216/20111110T193200', | ||
icalendar.format_value('PERIOD', [dt, dt2])); | ||
assert.equal('20111109T173216/P5DT3H', | ||
icalendar.format_value('PERIOD', [dt, 60*60*24*5 + 60*60*3])); | ||
assert.equal('FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', icalendar.format_value('RECUR', { | ||
BYMONTH: 11, BYDAY: '1SU', FREQ: 'YEARLY'})); | ||
assert.equal('-0800', icalendar.format_value('UTC-OFFSET', -800)); | ||
assert.equal('+1230', icalendar.format_value('UTC-OFFSET', 1230)); | ||
// Escape some things... | ||
assert.equal('\\\\ \\; \\, \\n', icalendar.format_value('TEXT', '\\ ; , \n')); | ||
}); | ||
it('value parsers', function() { | ||
assert.equal('\u0000\u0001\u0002\u0004\u0005\u0006', | ||
icalendar.parse_value('BINARY', 'AAECBAUG')); | ||
expect(icalendar.parse_value('DATE', '20111109')) | ||
.toEqual(new Date(2011,10,9)); | ||
expect(icalendar.parse_value('DATE', '20111109').date_only) | ||
.toEqual(true); | ||
assert.equal((new Date(0,0,0,17,32,16)).valueOf(), | ||
icalendar.parse_value('TIME', '173216').valueOf()); | ||
expect(icalendar.parse_value('DATE-TIME', '20111109T173216')) | ||
.toEqual(new Date(2011,10,9,17,32,16)); | ||
expect(icalendar.parse_value('DATE-TIME', '20110725T000000Z')) | ||
.toEqual(new Date(Date.UTC(2011,6,25))); | ||
assert.equal(60*60*24*7 + 60*60*24*2 + 60*60*3 + 60*4 + 5, | ||
icalendar.parse_value('DURATION', 'P1W2DT3H4M5S')); | ||
assert.deepEqual({FREQ: 'YEARLY', BYMONTH: 11, BYDAY: [1,0]}, | ||
icalendar.parse_value('RECUR', 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU').valueOf()); | ||
}); | ||
it('calendar object', function() { | ||
@@ -160,3 +97,3 @@ // assert that we create a valid empty iCal object | ||
it('parsing', function() { | ||
it('creates calendar clones', function() { | ||
var cal = icalendar.iCalendar.parse( | ||
@@ -174,35 +111,11 @@ 'BEGIN:VCALENDAR\r\n'+ | ||
assert.equal('-//Bobs Software Emporium//NONSGML Bobs Calendar//EN', | ||
cal.getPropertyValue('PRODID')); | ||
assert.equal('2.0', cal.getPropertyValue('VERSION')); | ||
assert.equal(1, cal.components['VEVENT'].length); | ||
var vevent = cal.components['VEVENT'][0]; | ||
assert.equal('This bit of text is long and should be '+ | ||
'split across multiple lines of output', | ||
vevent.getPropertyValue('DESCRIPTION')); | ||
assert.equal(new Date(2011, 11, 2, 16, 59).valueOf(), | ||
vevent.getPropertyValue('DTSTAMP').valueOf()); | ||
}); | ||
var cal2 = cal.clone(); | ||
it('parse torture test', function() { | ||
var cal = icalendar.iCalendar.parse( | ||
fs.readFileSync(__dirname+'/icalendar-test.ics', 'utf8')); | ||
expect(cal).toNotBe(cal2); | ||
expect(cal.components['VEVENT'][0]) | ||
.toNotBe(cal2.components['VEVENT'][0]); | ||
expect(cal2.toString()) | ||
.toEqual(cal.toString()) | ||
assert.equal('-//Google Inc//Google Calendar 70.9054//EN', | ||
cal.getPropertyValue('PRODID')); | ||
assert.equal('Gilsum NH Calendar', cal.getPropertyValue('X-WR-CALNAME')); | ||
assert.equal(153, cal.events().length); | ||
var vevent = cal.events()[0]; | ||
assert.equal('01meijjkccslk5acp8rngq30es@google.com', | ||
vevent.getPropertyValue('UID')); | ||
vevent = cal.events()[1]; | ||
assert.equal('jmdoebbto9vubpjf32aokpojb4@google.com', | ||
vevent.getPropertyValue('UID')); | ||
assert.equal('America/New_York', | ||
vevent.getProperty('DTSTART').getParameter('TZID')); | ||
assert.equal('2011-09-26T19:00:00.000Z', | ||
vevent.getPropertyValue('DTSTART').toISOString()); | ||
}); | ||
}); |
@@ -61,3 +61,97 @@ // Test search | ||
}); | ||
it('parsing', function() { | ||
var cal = icalendar.iCalendar.parse( | ||
'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'+ | ||
'UID:testuid@someotherplace.com\r\n'+ | ||
'DESCRIPTION:This bit of text is long and should be sp\r\n'+ | ||
' lit across multiple lines of output\r\n'+ | ||
'END:VEVENT\r\n'+ | ||
'END:VCALENDAR\r\n'); | ||
assert.equal('-//Bobs Software Emporium//NONSGML Bobs Calendar//EN', | ||
cal.getPropertyValue('PRODID')); | ||
assert.equal('2.0', cal.getPropertyValue('VERSION')); | ||
assert.equal(1, cal.components['VEVENT'].length); | ||
var vevent = cal.components['VEVENT'][0]; | ||
assert.equal('This bit of text is long and should be '+ | ||
'split across multiple lines of output', | ||
vevent.getPropertyValue('DESCRIPTION')); | ||
assert.equal(new Date(2011, 11, 2, 16, 59).valueOf(), | ||
vevent.getPropertyValue('DTSTAMP').valueOf()); | ||
}); | ||
it('parse torture test', function() { | ||
var cal = icalendar.iCalendar.parse( | ||
fs.readFileSync(__dirname+'/icalendar-test.ics', 'utf8')); | ||
assert.equal('-//Google Inc//Google Calendar 70.9054//EN', | ||
cal.getPropertyValue('PRODID')); | ||
assert.equal('Gilsum NH Calendar', cal.getPropertyValue('X-WR-CALNAME')); | ||
assert.equal(153, cal.events().length); | ||
var vevent = cal.events()[0]; | ||
assert.equal('01meijjkccslk5acp8rngq30es@google.com', | ||
vevent.getPropertyValue('UID')); | ||
vevent = cal.events()[1]; | ||
assert.equal('jmdoebbto9vubpjf32aokpojb4@google.com', | ||
vevent.getPropertyValue('UID')); | ||
assert.equal('America/New_York', | ||
vevent.getProperty('DTSTART').getParameter('TZID')); | ||
assert.equal('2011-09-26T19:00:00.000Z', | ||
vevent.getPropertyValue('DTSTART').toISOString()); | ||
}); | ||
it('uses timezone data parameter when parsing', function() { | ||
var cal = icalendar.parse_calendar( | ||
'BEGIN:VCALENDAR\r\n'+ | ||
'PRODID:-//Google Inc//Google Calendar 70.9054//EN\r\n'+ | ||
'VERSION:2.0\r\n'+ | ||
'BEGIN:VEVENT\r\n'+ | ||
'DTSTART;TZID=America/New_York:20110926T150000\r\n'+ | ||
'DTEND;TZID=America/New_York:20110926T160000\r\n'+ | ||
'DTSTAMP:20111206T175451Z\r\n'+ | ||
'UID:jmdoebbto9vubpjf32aokpojb4@google.com\r\n'+ | ||
'CREATED:20110913T133341Z\r\n'+ | ||
'LAST-MODIFIED:20110913T133341Z\r\n'+ | ||
'SUMMARY:Girl Scout Cadettes\r\n'+ | ||
'END:VEVENT\r\n'+ | ||
'END:VCALENDAR\r\n', | ||
'BEGIN:VCALENDAR\r\n'+ | ||
'PRODID:-//Google Inc//Google Calendar 70.9054//EN\r\n'+ | ||
'VERSION:2.0\r\n'+ | ||
'BEGIN:VTIMEZONE\r\n'+ | ||
'TZID:America/New_York\r\n'+ | ||
'X-LIC-LOCATION:America/New_York\r\n'+ | ||
'BEGIN:DAYLIGHT\r\n'+ | ||
'TZOFFSETFROM:-0500\r\n'+ | ||
'TZOFFSETTO:-0400\r\n'+ | ||
'TZNAME:EDT\r\n'+ | ||
'DTSTART:19700308T020000\r\n'+ | ||
'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU\r\n'+ | ||
'END:DAYLIGHT\r\n'+ | ||
'BEGIN:STANDARD\r\n'+ | ||
'TZOFFSETFROM:-0400\r\n'+ | ||
'TZOFFSETTO:-0500\r\n'+ | ||
'TZNAME:EST\r\n'+ | ||
'DTSTART:19701101T020000\r\n'+ | ||
'RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU\r\n'+ | ||
'END:STANDARD\r\n'+ | ||
'END:VTIMEZONE\r\n'+ | ||
'END:VCALENDAR\r\n' | ||
); | ||
var vevent = cal.getComponents('VEVENT')[0]; | ||
expect(vevent.getPropertyValue('DTSTART')) | ||
.toEqual(new Date(Date.UTC(2011,8,26,19,0,0))); | ||
expect(vevent.getPropertyValue('DTEND')) | ||
.toEqual(new Date(Date.UTC(2011,8,26,20,0,0))); | ||
}); | ||
}); | ||
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
150041
17
1401