Socket
Socket
Sign inDemoInstall

icalendar

Package Overview
Dependencies
Maintainers
2
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

icalendar - npm Package Compare versions

Comparing version 0.5.4 to 0.6.0

63

lib/base.js

@@ -28,2 +28,6 @@ // Copyright (C) 2011 Tri Tech Computers Ltd.

var properties = exports.properties = {
EXDATE: {
type: 'DATE-TIME',
list: true
},
DTSTAMP: {

@@ -76,3 +80,3 @@ type: 'DATE-TIME'

for(var prop in this.properties)
obj.addProperty(this.properties[prop]);
obj.addProperties(this.properties[prop]);

@@ -86,10 +90,16 @@ var comp = this.getComponents();

CalendarObject.prototype.addProperties = function(props) {
props.forEach(this.addProperty.bind(this));
}
CalendarObject.prototype.addProperty = function(prop, value, parameters) {
if(!(prop instanceof CalendarProperty))
if(!(prop instanceof CalendarProperty)) {
if(value === undefined) return;
prop = new CalendarProperty(prop, value, parameters);
}
else
prop = prop.clone();
// TODO: What about multiple occurances of the same property?
this.properties[prop.name] = prop;
this.properties[prop.name] = this.properties[prop.name] || [];
this.properties[prop.name].push(prop);
return prop;

@@ -130,10 +140,31 @@ }

CalendarObject.prototype.getProperty = function(prop) {
return this.properties[prop];
CalendarObject.prototype.getProperty = function(prop, i) {
return (this.properties[prop] || [])[i || 0];
}
CalendarObject.prototype.getPropertyValue = function(prop) {
return (this.properties[prop] || {}).value;
CalendarObject.prototype.getProperties = function(prop) {
return this.properties[prop] || [];
}
CalendarObject.prototype.getPropertyValue = function(prop, i) {
return (this.getProperty(prop, i) || {}).value;
}
CalendarObject.prototype.validate = function() {
var self = this;
var _schema = schema[self.element];
if(_schema && _schema.required_properties) {
_schema.required_properties.forEach(function(req) {
if(!self.getPropertyValue(req))
throw new Error(req+" is a required property of "+self.element);
});
}
for(var type in self.components) {
self.components[type].forEach(function(comp) {
comp.validate();
});
}
}
CalendarObject.prototype.toString = function() {

@@ -156,4 +187,7 @@ // Make sure output always includes a VCALENDAR object

var lines = ['BEGIN:'+this.element];
for(var i in this.properties)
lines.push.apply(lines, this.properties[i].format());
for(var i in this.properties) {
this.properties[i].forEach(function(prop) {
lines.push.apply(lines, prop.format());
});
}

@@ -202,3 +236,10 @@ for(var comp in this.components) {

CalendarProperty.prototype.format = function() {
var data = new Buffer(this.name+':'+format_value(this.type, this.value, this.parameters));
var params = [];
for(var k in this.parameters)
params.push(k+'='+this.parameters[k]);
if(params.length)
params = ';'+params.join(';');
var data = new Buffer(this.name+params+':'+format_value(this.type, this.value, this.parameters));
var pos = 0, len;

@@ -205,0 +246,0 @@ var output = [];

8

lib/event.js

@@ -0,1 +1,2 @@

"use strict";
// Copyright (C) 2011 Tri Tech Computers Ltd.

@@ -72,5 +73,6 @@ //

return new RRule(rr,
this.getPropertyValue('DTSTART'),
this.getPropertyValue('DTEND'));
return new RRule(rr, {
DTSTART: this.getPropertyValue('DTSTART'),
DTEND: this.getPropertyValue('DTEND')
});
}

@@ -77,0 +79,0 @@

@@ -81,4 +81,4 @@ // Copyright (C) 2011 Tri Tech Computers Ltd.

else {
value = parse_value((properties[element] || {}).type,
value, parameters, cal);
var prop = properties[element] || {};
value = parse_value(prop.type, value, parameters, cal, prop.list);
component.addProperty(element, value, parameters);

@@ -117,3 +117,3 @@ return this_state;

var j = i;
while(j+1<data.length && data[j+1][0] == ' ')
while(j+1<data.length && (data[j+1][0] === ' ' || data[j+1][0] === '\t'))
++j;

@@ -120,0 +120,0 @@

@@ -45,7 +45,11 @@ // Copyright (C) 2011 Tri Tech Computers Ltd.

return new Date(Date.UTC.apply(null, dt));
//udt.date_only = dt.date_only;
return udt;
}
function from_utc_date(dt) {
return new Date(dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate(),
dt.getUTCHours(), dt.getUTCMinutes(), dt.getUTCSeconds(), dt.getUTCMilliseconds());
function from_utc_date(udt) {
var dt = new Date(udt.getUTCFullYear(), udt.getUTCMonth(), udt.getUTCDate(),
udt.getUTCHours(), udt.getUTCMinutes(), udt.getUTCSeconds(), udt.getUTCMilliseconds());
//dt.date_only = udt.date_only;
return dt;
}

@@ -109,6 +113,12 @@

var RRule = exports.RRule = function(rule, start, end) {
this.start = start ? to_utc_date(start) : null;
this.end = end ? to_utc_date(end) : null;
var RRule = exports.RRule = function(rule, options, dtend) {
if(options instanceof Date)
options = { DTSTART: options, DTEND: dtend };
options = options || {};
this.start = options.DTSTART ? to_utc_date(options.DTSTART) : null;
this.end = options.DTEND ? to_utc_date(options.DTEND) : null;
this.exceptions = options.EXDATE || [];
if(typeof rule === 'string')

@@ -169,4 +179,21 @@ rule = RRule.parse(rule);

var next = freq.next(this.rule, this.start, after);
NextOccurs:
while(true) {
var next = freq.next(this.rule, this.start, after);
// Exclude EXDATES
var nextInLocal = from_utc_date(next);
for(var i=0; i < this.exceptions.length; i++) {
var exdate = this.exceptions[i];
if((exdate.valueOf() == nextInLocal.valueOf())
|| (exdate.date_only && y(exdate) == y(nextInLocal)
&& m(exdate) == m(nextInLocal) && d(exdate) == d(nextInLocal))) {
after = next;
continue NextOccurs;
}
}
break;
}
// Date is off the end of the spectrum...

@@ -265,2 +292,14 @@ if(this.end && next > this.end)

}
},
EXDATE: {
parse: function(v) {
return v.split(',').map(function(dt) {
return dt.length == 8 ? types.parse_value('DATE', dt) : types.parse_value('DATE-TIME', dt);
});
},
format: function(v) {
return v.map(function(dt) {
return types.format_value(dt.date_only ? 'DATE' : 'DATE-TIME', dt);
}).join(',');
}
}

@@ -277,2 +316,7 @@ };

var next = new Date(after);
set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));
var interval = rule.INTERVAL || 1;

@@ -286,7 +330,3 @@

for(var i=0; i<2; ++i) {
next = byday(rule.BYDAY, next);
set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));
next = byday(rule.BYDAY, next, after);

@@ -305,2 +345,7 @@ if(next.valueOf() > after.valueOf())

var next = new Date(after);
set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));
var interval = rule.INTERVAL || 1;

@@ -314,3 +359,3 @@

while(true) {
next = byday(rule.BYDAY, next);
next = byday(rule.BYDAY, next, after);

@@ -329,6 +374,2 @@ // Fall back to the start day of the week

set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));

@@ -348,2 +389,7 @@ if(next.valueOf() > after.valueOf()

var next = new Date(after);
set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));
var interval = rule.INTERVAL || 1;

@@ -358,5 +404,5 @@

for(var i=0; i<2; ++i) {
set_d(next, 1);
next = byday(rule.BYDAY, next);
next = bymonthday(rule.BYMONTHDAY, next);
if (i) set_d(next, 1); // Start at the beginning of the month for subsequent months
next = byday(rule.BYDAY, next, after);
next = bymonthday(rule.BYMONTHDAY, next, after);

@@ -367,7 +413,2 @@ // Fall back to the start day of the month

set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));
if(next.valueOf() > after.valueOf())

@@ -386,2 +427,8 @@ break;

var next = new Date(after);
// TODO: Add actual byhour/minute/second methods
set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));
var interval = rule.INTERVAL || 1;

@@ -396,5 +443,5 @@

for(var i=0; i<2; ++i) {
next = bymonth(rule.BYMONTH, next, i);
next = bymonthday(rule.BYMONTHDAY, next);
next = byday(rule.BYDAY, next, i);
next = bymonth(rule.BYMONTH, next);
next = bymonthday(rule.BYMONTHDAY, next, after);
next = byday(rule.BYDAY, next, after);

@@ -407,8 +454,2 @@ // Fall back the the start month and day of the month

// TODO: Add actual byhour/minute/second methods
set_hr(next, hr(start));
set_min(next, min(start));
set_sec(next, sec(start));
set_ms(next, ms(start));
// Don't loop back again if we found a new date

@@ -461,3 +502,3 @@ if(next.valueOf() > after.valueOf())

function bymonthday(rules, dt) {
function bymonthday(rules, dt, after) {
if(!rules || !rules.length) return dt;

@@ -467,3 +508,3 @@

var newdt = set_d(new Date(dt), rule);
return (newdt < dt ? null : newdt);
return (newdt.valueOf() <= after.valueOf() ? null : newdt);
});

@@ -477,3 +518,3 @@

// Advance to the next day that satisfies the byday rule...
function byday(rules, dt) {
function byday(rules, dt, after) {
if(!rules || !rules.length) return dt;

@@ -489,3 +530,3 @@

if(rule[0] > 0) {
var wk = 0 | (d(newdt) / 7) + 1;
var wk = 0 | ((d(newdt) - 1) / 7) + 1;
if(wk > rule[0]) return null;

@@ -508,4 +549,4 @@

// Don't look outside the current month...
if(m(newdt) !== m(dt)) return null;
// Ignore if it's a past date...
if (newdt.valueOf() <= after.valueOf()) return null;

@@ -512,0 +553,0 @@ return newdt;

@@ -171,2 +171,6 @@ // Copyright (C) 2011 Tri Tech Computers Ltd.

return value.toString().replace(/([\\,;])/g, "\\$1").replace(/\n/g, "\\n");
},
parse: function(value) {
return value.replace(/\\([\\,;])/g, "$1")
.replace(/\\[nN]/g, '\n');
}

@@ -219,6 +223,14 @@ },

return fmt.format(value, parameters || {});
// PERIOD is a corner case here; it's an array of two values
if(Array.isArray(value) && type !== 'PERIOD'
|| type === 'PERIOD' && value[0] && Array.isArray(value[0]))
return value.map(function(v) { return fmt.format(v, parameters || {}); }).join(',');
else
return fmt.format(value, parameters || {});
}
var parse_value = exports.parse_value = function(type, value, parameters, calendar) {
var parse_value = exports.parse_value = function(type, value, parameters, calendar, expect_list) {
if(expect_list)
return value.split(',').map(function(x) { return parse_value(type, x, parameters, calendar); });
var fmt = _types[type || 'TEXT'];

@@ -225,0 +237,0 @@ if(fmt === undefined)

{
"name": "icalendar",
"version": "0.5.4",
"version": "0.6.0",
"author": "James Emerton <james@tri-tech.com>",

@@ -5,0 +5,0 @@ "description": "RFC5545 iCalendar parser/generator",

@@ -56,5 +56,8 @@ iCalendar for Node

* RDATE and EXDATE are not implemented, but support is planned
* RDATE is not yet implemented
* RECURRENCE-ID and multiple related VEVENTS are not currently supported
* Documentation is pretty weak
Contact

@@ -61,0 +64,0 @@ -------

@@ -129,2 +129,19 @@ // Test search

});
it('formats objects with multiple occurrences of a property', function() {
var vevent = new icalendar.VEvent('testuid@tri-tech.com');
vevent.addProperty('EXDATE', new Date(Date.UTC(2012,2,3, 11,30,00)));
vevent.addProperty('EXDATE', new Date(2011,1,2), { VALUE: 'DATE' });
var dtstamp = icalendar.format_value('DATE-TIME',vevent.getPropertyValue('DTSTAMP'));
assert.deepEqual([
'BEGIN:VEVENT',
'DTSTAMP:'+dtstamp,
'UID:testuid@tri-tech.com',
'EXDATE:20120303T113000Z',
'EXDATE;VALUE=DATE:20110202',
'END:VEVENT'
],
vevent.format());
});
});

@@ -34,2 +34,47 @@ // Test search

it("decodes escaped chars as per RFC", function() {
var cal = parse_calendar(
'BEGIN:VCALENDAR\r\n'+
'PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN\r\n'+
'VERSION:2.0\r\n'+
'BEGIN:VEVENT\r\n'+
'DESCRIPTION:Once upon a time\\; someone used a comma\\,\\nand a newline!\r\n'+
'DTEND:20120427T170000Z\r\n'+
'DTSTART:20120427T150000Z\r\n'+
'UID:testuid@someotherplace.com\r\n'+
'END:VEVENT\r\n'+
'END:VCALENDAR\r\n');
var vevent = cal.components['VEVENT'][0];
assert.equal('Once upon a time; someone used a comma,\nand a newline!',
vevent.getPropertyValue('DESCRIPTION'));
});
it("handles data using tabs for line continuations (Outlook)", function() {
var cal = parse_calendar(
'BEGIN:VCALENDAR\r\n'+
'PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN\r\n'+
'VERSION:2.0\r\n'+
'BEGIN:VEVENT\r\n'+
'CLASS:PUBLIC\r\n'+
'DESCRIPTION:Come print for free! We will have more ally prints\\, and all th\r\n'+
' e great colors you’ve come to expect from Open. \\n\\nFood! \\n\\nMusic! \\n\\\r\n'+
' nSun!\\n\r\n'+
'DTEND:20120427T170000Z\r\n'+
'DTSTART:20120427T150000Z\r\n'+
'UID:040000008200E00074C5B7101A82E00800000000C0132EF80F0ECD01000000000000000\r\n'+
' 0100000008B70F4BD4D344E418B5834B8D78C50A3\r\n'+
'END:VEVENT\r\n'+
'END:VCALENDAR\r\n');
var vevent = cal.components['VEVENT'][0];
assert.equal('Come print for free! We will have more ally prints, and all '+
'the great colors you’ve come to expect from Open. \n\nFood! \n\nMusic! \n\nSun!\n',
vevent.getPropertyValue('DESCRIPTION'));
assert.equal('040000008200E00074C5B7101A82E00800000000C0132EF80F0ECD0100000000000'+
'00000100000008B70F4BD4D344E418B5834B8D78C50A3',
vevent.getPropertyValue('UID'));
});
it('parses large collections', function() {

@@ -156,3 +201,24 @@ var cal = parse_calendar(

});
it('parses EXDATE properties', 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'+
'UID:testuid@someotherplace.com\r\n'+
'EXDATE:20120102T100000,20120203T100000\r\n'+
'EXDATE;VALUE=DATE:20120304\r\n'+
'END:VEVENT\r\n'+
'END:VCALENDAR\r\n');
var vevent = cal.getComponents('VEVENT')[0];
expect(vevent.getPropertyValue('EXDATE'))
.toEqual([new Date(2012,0,2, 10,0,0), new Date(2012,1,3, 10,0,0)]);
expect(vevent.getPropertyValue('EXDATE',1))
.toEqual([new Date(2012,2,4)]);
expect(vevent.getPropertyValue('EXDATE',1)[0].date_only).toBeTruthy();
});
});
var RRule = require('../lib/rrule').RRule;
function date_only(y, m, d) {
// Return a date object with the date_only set
var dt = new Date(y, m, d);
dt.date_only = true;
return dt;
}
describe("RRule", function() {

@@ -12,4 +19,11 @@ it("should parse RRULEs correctly", function() {

.toEqual({FREQ: 'WEEKLY', BYMONTH: [1,2,3]});
rrule = new RRule('FREQ=WEEKLY;BYMONTH=1,2,3').valueOf();
expect(rrule.FREQ).toEqual('WEEKLY');
expect(rrule.BYMONTH).toEqual([1,2,3]);
});
it("should format RRULEs correctly", function() {
expect(new RRule('FREQ=WEEKLY;BYMONTH=1,2,3').toString()).toEqual('FREQ=WEEKLY;BYMONTH=1,2,3');
});
it("respects UNTIL parts", function() {

@@ -48,2 +62,34 @@ var start = new Date(2011,0,1,2,0,0);

it("respects EXDATE date_only parts", function() {
var rrule = new RRule('FREQ=MONTHLY', {
DTSTART: new Date(2011,0,1),
EXDATE: [date_only(2011,1,1), date_only(2011,3,1)]
});
expect(rrule.nextOccurences(new Date(2010,11,31), 4))
.toEqual([
new Date(2011,0,1),
new Date(2011,2,1),
new Date(2011,4,1),
new Date(2011,5,1)
]);
});
// it("respects EXDATE full date parts", function() {
// var feb01 = new Date(2011,1,1);
// feb01.date_only = true;
//
// var rrule = new RRule('FREQ=MONTHLY', {
// DTSTART: new Date(2011,0,1,10),
// EXDATE: [feb01, new Date(2011,2,1, 10,0,0), new Date(2011,3,1, 12,0,0)]
// });
//
// expect(rrule.nextOccurences(new Date(2010,11,31), 3))
// .toEqual([
// new Date(2011,0,1,10),
// new Date(2011,3,1,10),
// new Date(2011,4,1,10)
// ]);
// });
describe("yearly recurrence", function() {

@@ -112,2 +158,16 @@ it("handles yearly recurrence", function() {

it("handles monthly recurrences with multiple BYDAY values", function () {
var rrule = new RRule('FREQ=MONTHLY;BYDAY=1MO,2TU,3WE', new Date(2012, 0, 1));
expect(rrule.nextOccurences(new Date(2012, 0, 1), 6))
.toEqual([
new Date(2012, 0, 2),
new Date(2012, 0, 10),
new Date(2012, 0, 18),
new Date(2012, 1, 6),
new Date(2012, 1, 14),
new Date(2012, 1, 15)
]);
});
it("handles monthly recurrences on the start day of month", function() {

@@ -232,4 +292,12 @@ var rrule = new RRule(RRule.parse('FREQ=MONTHLY'), new Date(2011,0,1));

});
it("handles daily weekend recurrence across month boundary", function() {
var rrule = new RRule('FREQ=DAILY;BYDAY=SA,SU', new Date(2012,3,14,17,0));
expect(rrule.next(new Date(2012,4,29,17,0)))
.toEqual(new Date(2012,5,2,17,0));
});
});
});

@@ -47,3 +47,16 @@

});
it('formats array values correctly', function() {
assert.equal(
'20120101,20120201',
icalendar.format_value('DATE', [new Date(2012,0,1), new Date(2012,1,1)]));
var dt = new Date(Date.UTC(2011,10,9,17,32,16));
var dt2 = new Date(Date.UTC(2011,10,10,19,32));
assert.equal(
'20111109T173216Z/20111110T193200Z,20111110T193200Z/20111109T173216Z',
icalendar.format_value('PERIOD', [[dt, dt2], [dt2, dt]]));
});
it('value parsers', function() {

@@ -50,0 +63,0 @@ assert.equal('\u0000\u0001\u0002\u0004\u0005\u0006',

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc