Commit 37db0820 authored by Mark Stenglein's avatar Mark Stenglein

ehehe 💥 it all!

parent 800a0436
Copyright (c) 2014 Sebastian Pekarek
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
This diff is collapsed.
'use strict';
var ical = require('../lib/'),
http = require('http'),
cal = ical({
domain: 'sebbo.net',
prodId: '//superman-industries.com//ical-generator//EN',
events: [
{
start: new Date(),
end: new Date(new Date().getTime() + 3600000),
summary: 'Example Event',
description: 'It works ;)',
url: 'http://sebbo.net/'
}
]
});
http.createServer(function(req, res) {
cal.serve(res);
}).listen(3000, '127.0.0.1', function() {
console.log('Server running at http://127.0.0.1:3000/');
});
\ No newline at end of file
var ical = require('../lib/'),
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 ;)');
console.log(cal.toString());
\ No newline at end of file
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
module.exports = function(grunt) {
'use strict';
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.initConfig({
jshint: {
options: {
jshintrc: true
},
lib: [
'lib/*.js',
'test/*.js'
]
},
watch: {
lib: {
files: ['lib/*.js', 'test/*.js'],
tasks: ['jshint:lib']
}
}
});
grunt.registerTask('default', ['jshint:lib']);
grunt.registerTask('dev', ['jshint:lib', 'watch']);
};
\ No newline at end of file
'use strict';
module.exports = {};
module.exports.formatDate = function formatDate(d, dateonly, floating) {
var s;
function pad(i) {
return (i < 10 ? '0' : '') + i;
}
s = d.getUTCFullYear();
s += pad(d.getUTCMonth() + 1);
s += pad(d.getUTCDate());
if(!dateonly) {
s += 'T';
s += pad(d.getUTCHours());
s += pad(d.getUTCMinutes());
s += pad(d.getUTCSeconds());
if(!floating) {
s += 'Z';
}
}
return s;
};
// For information about this format, see RFC 5545, section 3.3.5
// https://tools.ietf.org/html/rfc5545#section-3.3.5
module.exports.formatDateTZ = function formatDateTZ(property, date, eventData) {
var tzParam = '',
floating = eventData.floating;
if(eventData.timezone) {
tzParam = ';TZID=' + eventData.timezone;
// This isn't a 'floating' event because it has a timezone;
// but we use it to omit the 'Z' UTC specifier in formatDate()
floating = true;
}
return property + tzParam + ':' + module.exports.formatDate(date, false, floating);
};
module.exports.escape = function escape(str) {
return str.replace(/[\\;,"]/g, function(match) {
return '\\' + match;
}).replace(/(?:\r\n|\r|\n)/g, '\\n');
};
module.exports.duration = function duration(seconds) {
var string = '';
// < 0
if(seconds < 0) {
string = '-';
seconds *= -1;
}
string += 'P';
// DAYS
if(seconds >= 86400) {
string += Math.floor(seconds / 86400) + 'D';
seconds %= 86400;
}
if(!seconds && string.length > 1) {
return string;
}
string += 'T';
// HOURS
if(seconds >= 3600) {
string += Math.floor(seconds / 3600) + 'H';
seconds %= 3600;
}
// MINUTES
if(seconds >= 60) {
string += Math.floor(seconds / 60) + 'M';
seconds %= 60;
}
// SECONDS
if(seconds > 0) {
string += seconds + 'S';
}
else if(string.length <= 2) {
string += '0S';
}
return string;
};
module.exports.toJSON = function(object, attributes, options) {
var result = {};
options = options || {};
options.ignoreAttributes = options.ignoreAttributes || [];
options.hooks = options.hooks || {};
attributes.forEach(function(attribute) {
if(options.ignoreAttributes.indexOf(attribute) !== -1) {
return;
}
var value = object[attribute](),
newObj;
if(options.hooks[attribute]) {
value = options.hooks[attribute](value);
}
if(!value) {
return;
}
result[attribute] = value;
if(Array.isArray(result[attribute])) {
newObj = [];
result[attribute].forEach(function(object) {
newObj.push(object.toJSON());
});
result[attribute] = newObj;
}
});
return result;
};
module.exports.foldLines = function(input) {
return input.split('\r\n').map(function(line) {
return line.match(/(.{1,74})/g).join('\r\n ');
}).join('\r\n');
};
\ No newline at end of file
'use strict';
/**
* @author Sebastian Pekarek
* @module alarm
* @constructor ICalAlarm Alarm
*/
var ICalAlarm = function(_data, event) {
var attributes = ['type', 'trigger', 'triggerBefore', 'triggerAfter', 'repeat', 'interval', 'attach', 'description'],
vars,
i,
data;
if(!event) {
throw '`event` option required!';
}
vars = {
types: ['display', 'audio']
};
data = {
type: null,
trigger: null,
repeat: null,
repeatInterval: null,
attach: null,
description: null
};
/**
* Set/Get the alarm type
*
* @param type Type
* @since 0.2.1
* @returns {ICalAlarm|String}
*/
this.type = function(type) {
if(type === undefined) {
return data.type;
}
if(!type) {
data.type = null;
return this;
}
if(vars.types.indexOf(type) === -1) {
throw '`type` is not correct, must be either `display` or `audio`!';
}
data.type = type;
return this;
};
/**
* Set/Get seconds before event to trigger alarm
*
* @param {Number|Date} trigger Seconds before alarm triggeres
* @since 0.2.1
* @returns {ICalAlarm|Number|Date}
*/
this.trigger = function(trigger) {
if(trigger === undefined && data.trigger instanceof Date) {
return data.trigger;
}
if(trigger === undefined && data.trigger) {
return -1 * data.trigger;
}
if(trigger === undefined) {
return null;
}
if(!trigger) {
data.trigger = null;
return this;
}
if(trigger instanceof Date) {
data.trigger = trigger;
return this;
}
if(typeof trigger === 'number' && isFinite(trigger)) {
data.trigger = -1 * trigger;
return this;
}
throw '`trigger` is not correct, must be either typeof `Number` or `Date`!';
};
/**
* Set/Get seconds after event to trigger alarm
*
* @param {Number|Date} trigger Seconds after alarm triggeres
* @since 0.2.1
* @returns {ICalAlarm|Number|Date}
*/
this.triggerAfter = function(trigger) {
if(trigger === undefined) {
return data.trigger;
}
return this.trigger(typeof trigger === 'number' ? -1 * trigger : trigger);
};
/**
* Set/Get seconds before event to trigger alarm
*
* @param {Number|Date} trigger Seconds before alarm triggeres
* @since 0.2.1
* @alias trigger
* @returns {ICalAlarm|Number|Date}
*/
this.triggerBefore = this.trigger;
/**
* Set/Get Alarm Repetitions
*
* @param {Number} Number of repetitions
* @since 0.2.1
* @returns {ICalAlarm|Number}
*/
this.repeat = function(repeat) {
if(repeat === undefined) {
return data.repeat;
}
if(!repeat) {
data.repeat = null;
return this;
}
if(typeof repeat !== 'number' || !isFinite(repeat)) {
throw '`repeat` is not correct, must be numeric!';
}
data.repeat = repeat;
return this;
};
/**
* Set/Get Repeat Interval
*
* @param {Number} Interval in seconds
* @since 0.2.1
* @returns {ICalAlarm|Number|Null}
*/
this.interval = function(interval) {
if(interval === undefined) {
return data.interval;
}
if(!interval) {
data.interval = null;
return this;
}
if(typeof interval !== 'number' || !isFinite(interval)) {
throw '`interval` is not correct, must be numeric!';
}
data.interval = interval;
return this;
};
/**
* Set/Get Attachment
*
* @param {Object|String} File-URI or Object
* @since 0.2.1
* @returns {ICalAlarm|Object}
*/
this.attach = function(_attach) {
if(_attach === undefined) {
return data.attach;
}
if(!_attach) {
data.attach = null;
return this;
}
var attach = null;
if(typeof _attach === 'string') {
attach = {
uri: _attach,
mime: null
};
}
else if(typeof _attach === 'object') {
attach = {
uri: _attach.uri,
mime: _attach.mime || null
};
}
else {
throw '`attach` needs to be a valid formed string or an object. See https://github.com/sebbo2002/ical-generator#attachstringobject-attach';
}
if(!attach.uri) {
throw '`attach.uri` is empty!';
}
data.attach = {
uri: attach.uri,
mime: attach.mime
};
return this;
};
/**
* Set/Get the alarm description
*
* @param description Description
* @since 0.2.1
* @returns {ICalAlarm|String}
*/
this.description = function(description) {
if(description === undefined) {
return data.description;
}
if(!description) {
data.description = null;
return this;
}
data.description = description;
return this;
};
/**
* Export calender as JSON Object to use it later…
*
* @since 0.2.4
* @returns Object Calendar
*/
this.toJSON = function() {
var tools = require('./_tools.js');
return tools.toJSON(this, attributes);
};
/**
* Export Event to iCal
*
* @since 0.2.0
* @returns {String}
*/
this.generate = function() {
var tools = require('./_tools.js'),
g = 'BEGIN:VALARM\r\n';
if(!data.type) {
throw 'No value for `type` in ICalAlarm given!';
}
if(!data.trigger) {
throw 'No value for `trigger` in ICalAlarm given!';
}
// ACTION
g += 'ACTION:' + data.type.toUpperCase() + '\r\n';
if(data.trigger instanceof Date) {
g += 'TRIGGER;VALUE=DATE-TIME:' + tools.formatDate(data.trigger) + '\r\n';
}
else if(data.trigger > 0) {
g += 'TRIGGER;RELATED=END:' + tools.duration(data.trigger) + '\r\n';
}
else {
g += 'TRIGGER:' + tools.duration(data.trigger) + '\r\n';
}
// REPEAT
if(data.repeat && !data.interval) {
throw 'No value for `interval` in ICalAlarm given, but required for `repeat`!';
}
if(data.repeat) {
g += 'REPEAT:' + data.repeat + '\r\n';
}
// INTERVAL
if(data.interval && !data.repeat) {
throw 'No value for `repeat` in ICalAlarm given, but required for `interval`!';
}
if(data.interval) {
g += 'DURATION:' + tools.duration(data.interval) + '\r\n';
}
// ATTACH
if(data.type === 'audio' && data.attach && data.attach.mime) {
g += 'ATTACH;FMTTYPE=' + data.attach.mime + ':' + data.attach.uri + '\r\n';
}
else if(data.type === 'audio' && data.attach) {
g += 'ATTACH;VALUE=URI:' + data.attach.uri + '\r\n';
}
else if(data.type === 'audio') {
g += 'ATTACH;VALUE=URI:Basso\r\n';
}
// DESCRIPTION
if(data.type === 'display' && data.description) {
g += 'DESCRIPTION:' + tools.escape(data.description) + '\r\n';
}
else if(data.type === 'display') {
g += 'DESCRIPTION:' + tools.escape(event.summary()) + '\r\n';
}
g += 'END:VALARM\r\n';
return g;
};
for(i in _data) {
if(_data.hasOwnProperty(i) && attributes.indexOf(i) > -1) {
this[i](_data[i]);
}
}
};
module.exports = ICalAlarm;
\ No newline at end of file
'use strict';
/**
* @author Sebastian Pekarek
* @module attendee
* @constructor ICalAttendee Attendee
*/
var ICalAttendee = function(_data, event) {
var attributes = ['name', 'email', 'role', 'status', 'type', 'delegatedTo', 'delegatedFrom', 'delegatesFrom', 'delegatesTo'],
vars,
i,
data;
if(!event) {
throw '`event` option required!';
}
vars = {
allowed: {
role: ['REQ-PARTICIPANT', 'NON-PARTICIPANT'],
status: ['ACCEPTED', 'TENTATIVE', 'DECLINED', 'DELEGATED'],
type: ['INDIVIDUAL', 'GROUP', 'RESOURCE', 'ROOM', 'UNKNOWN'] // ref: https://tools.ietf.org/html/rfc2445#section-4.2.3
}
};
data = {
name: null,
email: null,
status: null,
role: 'REQ-PARTICIPANT',
type: null,
delegatedTo: null,
delegatedFrom: null
};
function getAllowedRole(str) {
return getAllowedStringFor('role', str);
}
function getAllowedStatus(str) {
return getAllowedStringFor('status', str);
}
function getAllowedType(str) {
return getAllowedStringFor('type', str);
}
function getAllowedStringFor(type, str) {
if(!str || typeof(str) !== 'string') {
throw new Error('Input for `' + type + '` must be a non-empty string. You gave ' + str);
}
str = str.toUpperCase();
if(vars.allowed[type].indexOf(str) === -1) {
throw new Error('`' + type + '` must be one of the following: ' + vars.allowed[type].join(', ') + '!');
}
return str;
}
/**
* Set/Get the attendee's name
*
* @param name Name
* @since 0.2.0
* @returns {ICalAttendee|String}
*/
this.name = function(name) {
if(name === undefined) {
return data.name;
}
data.name = name || null;
return this;
};
/**
* Set/Get the attendee's email address
*
* @param email Email address
* @since 0.2.0
* @returns {ICalAttendee|String}
*/
this.email = function(email) {
if(!email) {
return data.email;
}
data.email = email;
return this;
};
/**
* Set/Get attendee's role
*
* @param {String} role
* @since 0.2.0
* @returns {ICalAttendee|String}
*/
this.role = function(role) {
if(role === undefined) {
return data.role;
}
data.role = getAllowedRole(role);
return this;
};
/**
* Set/Get attendee's status