Commit 67c9153f authored by Mark Stenglein's avatar Mark Stenglein Committed by GitHub
Browse files

Merge pull request #1 from srct/develop

move over new feature to @srct master
parents 3f0d0117 237e3a6b
...@@ -180,6 +180,10 @@ Use this method to set your feed's timezone. Is used to fill `TIMEZONE-ID` and ` ...@@ -180,6 +180,10 @@ Use this method to set your feed's timezone. Is used to fill `TIMEZONE-ID` and `
var cal = ical().timezone('Europe/Berlin'); var cal = ical().timezone('Europe/Berlin');
``` ```
#### method([_String_ method])
Calendar method. May be any of the following: `publish`, `request`, `reply`, `add`, `cancel`, `refresh`, `counter`, `declinecounter`.
#### ttl([_Number_ ttl]) #### ttl([_Number_ ttl])
...@@ -443,11 +447,6 @@ cal.attendees(); // --> [ICalAlarm, ICalAlarm] ...@@ -443,11 +447,6 @@ cal.attendees(); // --> [ICalAlarm, ICalAlarm]
Appointment URL Appointment URL
#### method([_String_ method])
Appointment method. May be any of the following: `publish`, `request`, `reply`, `add`, `cancel`, `refresh`, `counter`, `declinecounter`.
#### status([_String_ status]) #### status([_String_ status])
Appointment status. May be any of the following: `confirmed`, `tenative`, `cancelled`. Appointment status. May be any of the following: `confirmed`, `tenative`, `cancelled`.
...@@ -539,8 +538,8 @@ var cal = ical(), ...@@ -539,8 +538,8 @@ var cal = ical(),
event = cal.createEvent(), event = cal.createEvent(),
alarm = cal.createAlarm(); alarm = cal.createAlarm();
alarm.trigger(600); // -> 10 minutes after the event finishes alarm.triggerAfter(600); // -> 10 minutes after the event finishes
alarm.trigger(new Date()); // -> now alarm.triggerAfter(new Date()); // -> now
``` ```
......
var ical = require('ical-generator'),
cal = ical({domain: 'localhost'}),
event;
// overwrite domain
cal.domain('example.com');
event = cal.createEvent({
start: new Date(new Date().getTime() + 3600000),
end: new Date(new Date().getTime() + 7200000),
summary: 'Example Event',
description: 'It works ;)',
organizer: 'Organizer\'s Name <organizer@example.com>',
url: 'http://sebbo.net/'
});
// update event's description
event.description('It still works ;)');
cal.toString();
\ No newline at end of file
...@@ -8,10 +8,14 @@ ...@@ -8,10 +8,14 @@
*/ */
var ICalCalendar = function(_data) { var ICalCalendar = function(_data) {
var data = {}, var data = {},
attributes = ['domain', 'prodId', 'name', 'description', 'timezone', 'ttl', 'url', 'events'], attributes = ['domain', 'prodId', 'method', 'name', 'description', 'timezone', 'ttl', 'url', 'events'],
vars,
generate, generate,
i; i;
vars = {
allowedMethods: ['PUBLISH', 'REQUEST', 'REPLY', 'ADD', 'CANCEL', 'REFRESH', 'COUNTER', 'DECLINECOUNTER']
};
generate = function(calendar) { generate = function(calendar) {
var tools = require('./_tools.js'), var tools = require('./_tools.js'),
...@@ -28,6 +32,11 @@ var ICalCalendar = function(_data) { ...@@ -28,6 +32,11 @@ var ICalCalendar = function(_data) {
g += 'URL:' + data.url + '\r\n'; g += 'URL:' + data.url + '\r\n';
} }
// METHOD
if(data.method) {
g += 'METHOD:' + data.method + '\r\n';
}
// NAME // NAME
if(data.name) { if(data.name) {
g += 'NAME:' + data.name + '\r\n'; g += 'NAME:' + data.name + '\r\n';
...@@ -172,6 +181,31 @@ var ICalCalendar = function(_data) { ...@@ -172,6 +181,31 @@ var ICalCalendar = function(_data) {
}; };
/**
* Set/Get your feed's method
*
* @param {String} method
* @since 0.2.8
* @returns {ICalCalendar|String}
*/
this.method = function(method) {
if(method === undefined) {
return data.method;
}
if(!method) {
data.method = null;
return this;
}
if(vars.allowedMethods.indexOf(method.toUpperCase()) === -1) {
throw '`method` must be one of the following: ' + vars.allowedMethods.join(', ') + '!';
}
data.method = method.toUpperCase();
return this;
};
/** /**
* Set your feed's name… * Set your feed's name…
* *
...@@ -450,6 +484,7 @@ var ICalCalendar = function(_data) { ...@@ -450,6 +484,7 @@ var ICalCalendar = function(_data) {
this.clear = function() { this.clear = function() {
data.domain = require('os').hostname(); data.domain = require('os').hostname();
data.prodid = '//sebbo.net//ical-generator//EN'; data.prodid = '//sebbo.net//ical-generator//EN';
data.method = null;
data.name = null; data.name = null;
data.timezone = null; data.timezone = null;
data.ttl = null; data.ttl = null;
......
...@@ -17,7 +17,6 @@ var ICalEvent = function(_data, calendar) { ...@@ -17,7 +17,6 @@ var ICalEvent = function(_data, calendar) {
} }
vars = { vars = {
allowedMethods: ['PUBLISH', 'REQUEST', 'REPLY', 'ADD', 'CANCEL', 'REFRESH', 'COUNTER', 'DECLINECOUNTER'],
allowedRepeatingFreq: ['SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY'], allowedRepeatingFreq: ['SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY'],
allowedStatuses: ['CONFIRMED', 'TENATIVE', 'CANCELLED'] allowedStatuses: ['CONFIRMED', 'TENATIVE', 'CANCELLED']
}; };
...@@ -38,7 +37,6 @@ var ICalEvent = function(_data, calendar) { ...@@ -38,7 +37,6 @@ var ICalEvent = function(_data, calendar) {
organizer: null, organizer: null,
attendees: [], attendees: [],
alarms: [], alarms: [],
method: null,
status: null, status: null,
url: null url: null
}; };
...@@ -309,12 +307,12 @@ var ICalEvent = function(_data, calendar) { ...@@ -309,12 +307,12 @@ var ICalEvent = function(_data, calendar) {
data.repeating.byDay = []; data.repeating.byDay = [];
repeating.byDay.forEach(function(symbol) { repeating.byDay.forEach(function(symbol) {
var s = symbol.toString().toUpperCase(); var s = symbol.toString().toUpperCase().match(/^(\d*||-\d+)(\w+)$/);
if(['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'].indexOf(s) === -1) { if(['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'].indexOf(s[2]) === -1) {
throw '`repeating.byDay` contains invalid value `' + s + '`!'; throw '`repeating.byDay` contains invalid value `' + s[2] + '`!';
} }
data.repeating.byDay.push(s); data.repeating.byDay.push(s[1]+s[2]);
}); });
} }
...@@ -348,6 +346,26 @@ var ICalEvent = function(_data, calendar) { ...@@ -348,6 +346,26 @@ var ICalEvent = function(_data, calendar) {
}); });
} }
if(repeating.exclude) {
if(!Array.isArray(repeating.exclude)) {
repeating.exclude = [repeating.exclude];
}
data.repeating.exclude = [];
repeating.exclude.forEach(function(excludedDate) {
var originalDate = excludedDate;
if(typeof(excludedDate == 'string')) {
excludedDate = new Date(excludedDate);
}
if(Object.prototype.toString.call(excludedDate) !== '[object Date]' || isNaN(excludedDate.getTime())) {
throw '`repeating.exclude` contains invalid value `' + originalDate + '`!';
}
data.repeating.exclude.push(excludedDate);
});
}
return this; return this;
}; };
...@@ -542,26 +560,23 @@ var ICalEvent = function(_data, calendar) { ...@@ -542,26 +560,23 @@ var ICalEvent = function(_data, calendar) {
/** /**
* Set/Get the event's method * Set/Get your feed's method
* *
* @param {String} method * @param {String} method
* @since 0.2.0 * @since 0.2.0
* @deprecated since 0.2.8
* @returns {ICalEvent|String} * @returns {ICalEvent|String}
*/ */
this.method = function(method) { this.method = function(method) {
if(method === undefined) { if(method === undefined) {
return data.method; return calendar.method();
} }
if(!method) { if(!method) {
data.method = null; calendar.method(null);
return this; return this;
} }
if(vars.allowedMethods.indexOf(method.toUpperCase()) === -1) { calendar.method(method);
throw '`method` must be one of the following: ' + vars.allowedMethods.join(', ') + '!';
}
data.method = method.toUpperCase();
return this; return this;
}; };
...@@ -693,6 +708,18 @@ var ICalEvent = function(_data, calendar) { ...@@ -693,6 +708,18 @@ var ICalEvent = function(_data, calendar) {
} }
g += '\r\n'; g += '\r\n';
// REPEATING EXCLUSION
if(data.repeating.exclude) {
g += 'EXDATE:';
var sArr = [];
data.repeating.exclude.forEach(function(excludedDate) {
sArr.push(tools.formatDate(excludedDate));
});
g += sArr.join(',');
g += '\r\n';
}
} }
// SUMMARY // SUMMARY
...@@ -728,10 +755,7 @@ var ICalEvent = function(_data, calendar) { ...@@ -728,10 +755,7 @@ var ICalEvent = function(_data, calendar) {
g += 'URL;VALUE=URI:' + tools.escape(data.url) + '\r\n'; g += 'URL;VALUE=URI:' + tools.escape(data.url) + '\r\n';
} }
// METHOD & STATUS // STATUS
if(data.method) {
g += 'METHOD:' + data.method.toUpperCase() + '\r\n';
}
if(data.status) { if(data.status) {
g += 'STATUS:' + data.status.toUpperCase() + '\r\n'; g += 'STATUS:' + data.status.toUpperCase() + '\r\n';
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"name": "ical-generator", "name": "ical-generator",
"description": "ical-generator is a small piece of code which generates ical calendar files", "description": "ical-generator is a small piece of code which generates ical calendar files",
"author": "Sebastian Pekarek <mail@sebbo.net>", "author": "Sebastian Pekarek <mail@sebbo.net>",
"version": "0.2.7", "version": "0.2.8-dev",
"bugs": { "bugs": {
"url": "http://github.com/sebbo2002/ical-generator/issues", "url": "http://github.com/sebbo2002/ical-generator/issues",
"email": "bugs@sebbo.net" "email": "bugs@sebbo.net"
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
"scripts": { "scripts": {
"test": "grunt && istanbul cover _mocha -- -R spec --no-colors" "test": "grunt && istanbul cover _mocha -- -R spec --no-colors"
}, },
"tonicExampleFilename": "./example/example_tonic.js",
"preferGlobal": false, "preferGlobal": false,
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
......
BEGIN:VCALENDAR BEGIN:VCALENDAR
VERSION:2.0 VERSION:2.0
PRODID:-//sebbo.net//ical-generator.tests//EN PRODID:-//sebbo.net//ical-generator.tests//EN
METHOD:ADD
BEGIN:VEVENT BEGIN:VEVENT
UID:123@sebbo.net UID:123@sebbo.net
SEQUENCE:0 SEQUENCE:0
...@@ -12,7 +13,6 @@ X-MICROSOFT-MSNCALENDAR-ALLDAYEVENT:TRUE ...@@ -12,7 +13,6 @@ X-MICROSOFT-MSNCALENDAR-ALLDAYEVENT:TRUE
SUMMARY:Sample Event SUMMARY:Sample Event
ORGANIZER;CN="Sebastian Pekarek":mailto:mail@sebbo.net ORGANIZER;CN="Sebastian Pekarek":mailto:mail@sebbo.net
URL;VALUE=URI:http://sebbo.net/ URL;VALUE=URI:http://sebbo.net/
METHOD:ADD
STATUS:CONFIRMED STATUS:CONFIRMED
END:VEVENT END:VEVENT
END:VCALENDAR END:VCALENDAR
\ No newline at end of file
...@@ -8,6 +8,7 @@ DTSTAMP:20131004T233453Z ...@@ -8,6 +8,7 @@ DTSTAMP:20131004T233453Z
DTSTART:20131004T223930Z DTSTART:20131004T223930Z
DTEND:20131006T231500Z DTEND:20131006T231500Z
RRULE:FREQ=MONTHLY RRULE:FREQ=MONTHLY
EXDATE:20131006T231500Z
SUMMARY:repeating by month SUMMARY:repeating by month
END:VEVENT END:VEVENT
BEGIN:VEVENT BEGIN:VEVENT
......
BEGIN:VCALENDAR BEGIN:VCALENDAR
VERSION:2.0 VERSION:2.0
PRODID:-//sebbo.net//ical-generator.tests//EN PRODID:-//sebbo.net//ical-generator.tests//EN
METHOD:PUBLISH
BEGIN:VEVENT BEGIN:VEVENT
UID:123@sebbo.net UID:123@sebbo.net
SEQUENCE:0 SEQUENCE:0
DTSTAMP:20131004T233453Z DTSTAMP:20131004T233453Z
DTSTART;VALUE=DATE:20131004 DTSTART;VALUE=DATE:20131004
DTEND;VALUE=DATE:20131006
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE X-MICROSOFT-CDO-ALLDAYEVENT:TRUE
X-MICROSOFT-MSNCALENDAR-ALLDAYEVENT:TRUE X-MICROSOFT-MSNCALENDAR-ALLDAYEVENT:TRUE
SUMMARY:Sample Event SUMMARY:Sample Event
...@@ -26,7 +26,6 @@ TRIGGER:-PT1H ...@@ -26,7 +26,6 @@ TRIGGER:-PT1H
DESCRIPTION:I'm a reminder :) DESCRIPTION:I'm a reminder :)
END:VALARM END:VALARM
URL;VALUE=URI:http://sebbo.net/ URL;VALUE=URI:http://sebbo.net/
METHOD:ADD
STATUS:CONFIRMED STATUS:CONFIRMED
END:VEVENT END:VEVENT
END:VCALENDAR END:VCALENDAR
\ No newline at end of file
...@@ -15,7 +15,6 @@ UID:2@sebbo.net ...@@ -15,7 +15,6 @@ UID:2@sebbo.net
SEQUENCE:0 SEQUENCE:0
DTSTAMP:20131004T233453Z DTSTAMP:20131004T233453Z
DTSTART:20131004T223930Z DTSTART:20131004T223930Z
DTEND:20131006T231500Z
RRULE:FREQ=DAILY;COUNT=2;BYDAY=MO,WE,FR RRULE:FREQ=DAILY;COUNT=2;BYDAY=MO,WE,FR
SUMMARY:repeating on Mo/We/Fr\, twice SUMMARY:repeating on Mo/We/Fr\, twice
END:VEVENT END:VEVENT
......
...@@ -293,6 +293,42 @@ describe('ical-generator 0.1.x', function() { ...@@ -293,6 +293,42 @@ describe('ical-generator 0.1.x', function() {
}, /event\.repeating\.until must be a Date Object/); }, /event\.repeating\.until must be a Date Object/);
}); });
it('should throw error when repeating.exclude is not valid', function() {
var generator = require(__dirname + '/../lib/index.js'),
cal = generator();
assert.throws(function() {
cal.createEvent({
start: new Date(),
end: new Date(),
summary: 'test',
repeating: {
freq: 'DAILY',
interval: 2,
byDay: ['SU'],
exclude: 'FOO'
}
});
}, /`repeating\.exclude` contains invalid value `FOO`/);
});
it('should throw error when repeating.exclude is not valid (should throw on first err value', function() {
var generator = require(__dirname + '/../lib/index.js'),
cal = generator();
assert.throws(function() {
cal.createEvent({
start: new Date(),
end: new Date(),
summary: 'test',
repeating: {
freq: 'DAILY',
interval: 2,
byDay: ['SU'],
exclude: [new Date(), 'BAR', 'FOO']
}
});
}, /`repeating\.exclude` contains invalid value `BAR`/);
});
it('should throw error when summary is empty', function() { it('should throw error when summary is empty', function() {
var generator = require(__dirname + '/../lib/index.js'), var generator = require(__dirname + '/../lib/index.js'),
cal = generator(); cal = generator();
...@@ -346,7 +382,7 @@ describe('ical-generator 0.1.x', function() { ...@@ -346,7 +382,7 @@ describe('ical-generator 0.1.x', function() {
summary: 'hello', summary: 'hello',
method: 'hello world' method: 'hello world'
}); });
}, /event\.method must be one of the following/); }, /method must be one of the following/);
}); });
it('should throw an error if status is not allowed', function() { it('should throw an error if status is not allowed', function() {
...@@ -470,7 +506,8 @@ describe('ical-generator 0.1.x', function() { ...@@ -470,7 +506,8 @@ describe('ical-generator 0.1.x', function() {
stamp: new Date('Fr Oct 04 2013 23:34:53 UTC'), stamp: new Date('Fr Oct 04 2013 23:34:53 UTC'),
summary: 'repeating by month', summary: 'repeating by month',
repeating: { repeating: {
freq: 'MONTHLY' freq: 'MONTHLY',
exclude: new Date('Fr Oct 06 2013 23:15:00 UTC')
} }
}); });
......
...@@ -119,6 +119,40 @@ describe('ical-generator 0.2.x / ICalCalendar', function() { ...@@ -119,6 +119,40 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
}); });
}); });
describe('method()', function() {
it('setter should return this', function() {
var c = ical();
assert.deepEqual(c, c.method(null));
assert.deepEqual(c, c.method('publish'));
});
it('getter should return value', function() {
var c = ical();
assert.equal(c.method(), null);
c.method(null);
assert.equal(c.method(), null);
c.method('publish');
assert.equal(c.method(), 'PUBLISH');
c.method(null);
assert.equal(c.method(), null);
});
it('should throw error when method not allowed', function() {
var c = ical();
assert.throws(function() {
c.method('KICK ASS');
}, /`method`/);
});
it('should change something', function() {
var c = ical({method: 'publish'}),
str = c.toString();
c.method('add');
assert.ok(str !== c.toString());
});
});
describe('name()', function() { describe('name()', function() {
it('setter should return this', function() { it('setter should return this', function() {
var cal = ical(); var cal = ical();
...@@ -757,12 +791,13 @@ describe('ical-generator 0.2.x / ICalCalendar', function() { ...@@ -757,12 +791,13 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
freq: 'monthly', freq: 'monthly',
count: 5, count: 5,
interval: 2, interval: 2,
exclude: new Date(),
unitl: new Date() unitl: new Date()
})); }));
}); });
it('getter should return value', function() { it('getter should return value', function() {
var options = {freq: 'MONTHLY', count: 5, interval: 2, until: new Date()}, var options = {freq: 'MONTHLY', count: 5, interval: 2, exclude: new Date(), until: new Date()},
e = ical().createEvent(); e = ical().createEvent();
assert.deepEqual(e.repeating(), null); assert.deepEqual(e.repeating(), null);
e.repeating(options); e.repeating(options);
...@@ -952,6 +987,40 @@ describe('ical-generator 0.2.x / ICalCalendar', function() { ...@@ -952,6 +987,40 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
}); });
}, /`repeating\.byMonthDay` contains invalid value `32`/); }, /`repeating\.byMonthDay` contains invalid value `32`/);
}); });
it('should throw error when repeating.exclude is not valid', function() {
var cal = ical();
assert.throws(function() {
cal.createEvent({
start: new Date(),
end: new Date(),
summary: 'test',
repeating: {
freq: 'DAILY',
interval: 2,
byDay: ['SU'],
exclude: 'FOO'
}
});
}, /`repeating\.exclude` contains invalid value `FOO`/);
});
it('should throw error when repeating.exclude is not valid (should throw on first err value', function() {
var cal = ical();
assert.throws(function() {
cal.createEvent({
start: new Date(),
end: new Date(),
summary: 'test',
repeating: {
freq: 'DAILY',
interval: 2,
byDay: ['SU'],
exclude: [new Date(), 'BAR', 'FOO']
}
});
}, /`repeating\.exclude` contains invalid value `BAR`/);
});
});