From 7b4b7dffa226ec5454e134d222490efa84bc3584 Mon Sep 17 00:00:00 2001 From: Matt Bauer Date: Thu, 13 Jun 2019 09:36:31 -0500 Subject: [PATCH 1/5] =?UTF-8?q?Update=20calendar=E2=80=99s=20vendored=20ic?= =?UTF-8?q?al.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/vendor/ical.js/.travis.yml | 4 +- .../calendar/vendor/ical.js/example.js | 23 ++-- .../calendar/vendor/ical.js/example_rrule.js | 118 ++++++++++++++++ .../vendor/ical.js/examples/example_rrule.ics | 40 ++++++ .../calendar/vendor/ical.js/node-ical.js | 74 +++++----- .../calendar/vendor/ical.js/package.json | 9 +- .../default/calendar/vendor/ical.js/readme.md | 39 ++++-- .../calendar/vendor/ical.js/test/test.js | 127 ++++++++++++++++-- .../calendar/vendor/ical.js/test/test12.ics | 19 +++ .../calendar/vendor/ical.js/test/test13.ics | 57 ++++++++ .../calendar/vendor/ical.js/test/test14.ics | 33 +++++ 11 files changed, 468 insertions(+), 75 deletions(-) create mode 100644 modules/default/calendar/vendor/ical.js/example_rrule.js create mode 100644 modules/default/calendar/vendor/ical.js/examples/example_rrule.ics create mode 100644 modules/default/calendar/vendor/ical.js/test/test12.ics create mode 100644 modules/default/calendar/vendor/ical.js/test/test13.ics create mode 100644 modules/default/calendar/vendor/ical.js/test/test14.ics diff --git a/modules/default/calendar/vendor/ical.js/.travis.yml b/modules/default/calendar/vendor/ical.js/.travis.yml index 0a4c7980..d5d4c1e3 100644 --- a/modules/default/calendar/vendor/ical.js/.travis.yml +++ b/modules/default/calendar/vendor/ical.js/.travis.yml @@ -1,6 +1,4 @@ language: node_js node_js: - - "0.10" - - "0.12" - - "4.2" + - "8.9" install: npm install diff --git a/modules/default/calendar/vendor/ical.js/example.js b/modules/default/calendar/vendor/ical.js/example.js index aceb0e7d..7b41f1ad 100644 --- a/modules/default/calendar/vendor/ical.js/example.js +++ b/modules/default/calendar/vendor/ical.js/example.js @@ -1,13 +1,16 @@ -var ical = require('ical') - , months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] +'use strict'; +const ical = require('ical'); +const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; -ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, function(err, data){ - for (var k in data){ - if (data.hasOwnProperty(k)){ - var ev = data[k] - console.log("Conference", ev.summary, 'is in', ev.location, 'on the', ev.start.getDate(), 'of', months[ev.start.getMonth()] ); - } - } -}) +ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, function (err, data) { + for (let k in data) { + if (data.hasOwnProperty(k)) { + var ev = data[k]; + if (data[k].type == 'VEVENT') { + console.log(`${ev.summary} is in ${ev.location} on the ${ev.start.getDate()} of ${months[ev.start.getMonth()]} at ${ev.start.toLocaleTimeString('en-GB')}`); + } + } + } +}); diff --git a/modules/default/calendar/vendor/ical.js/example_rrule.js b/modules/default/calendar/vendor/ical.js/example_rrule.js new file mode 100644 index 00000000..6233c4b2 --- /dev/null +++ b/modules/default/calendar/vendor/ical.js/example_rrule.js @@ -0,0 +1,118 @@ +var ical = require('./node-ical') +var moment = require('moment') + +var data = ical.parseFile('./examples/example_rrule.ics'); + +// Complicated example demonstrating how to handle recurrence rules and exceptions. + +for (var k in data) { + + // When dealing with calendar recurrences, you need a range of dates to query against, + // because otherwise you can get an infinite number of calendar events. + var rangeStart = moment("2017-01-01"); + var rangeEnd = moment("2017-12-31"); + + + var event = data[k] + if (event.type === 'VEVENT') { + + var title = event.summary; + var startDate = moment(event.start); + var endDate = moment(event.end); + + // Calculate the duration of the event for use with recurring events. + var duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); + + // Simple case - no recurrences, just print out the calendar event. + if (typeof event.rrule === 'undefined') + { + console.log('title:' + title); + console.log('startDate:' + startDate.format('MMMM Do YYYY, h:mm:ss a')); + console.log('endDate:' + endDate.format('MMMM Do YYYY, h:mm:ss a')); + console.log('duration:' + moment.duration(duration).humanize()); + console.log(); + } + + // Complicated case - if an RRULE exists, handle multiple recurrences of the event. + else if (typeof event.rrule !== 'undefined') + { + // For recurring events, get the set of event start dates that fall within the range + // of dates we're looking for. + var dates = event.rrule.between( + rangeStart.toDate(), + rangeEnd.toDate(), + true, + function(date, i) {return true;} + ) + + // The "dates" array contains the set of dates within our desired date range range that are valid + // for the recurrence rule. *However*, it's possible for us to have a specific recurrence that + // had its date changed from outside the range to inside the range. One way to handle this is + // to add *all* recurrence override entries into the set of dates that we check, and then later + // filter out any recurrences that don't actually belong within our range. + if (event.recurrences != undefined) + { + for (var r in event.recurrences) + { + // Only add dates that weren't already in the range we added from the rrule so that + // we don't double-add those events. + if (moment(new Date(r)).isBetween(rangeStart, rangeEnd) != true) + { + dates.push(new Date(r)); + } + } + } + + // Loop through the set of date entries to see which recurrences should be printed. + for(var i in dates) { + + var date = dates[i]; + var curEvent = event; + var showRecurrence = true; + var curDuration = duration; + + startDate = moment(date); + + // Use just the date of the recurrence to look up overrides and exceptions (i.e. chop off time information) + var dateLookupKey = date.toISOString().substring(0, 10); + + // For each date that we're checking, it's possible that there is a recurrence override for that one day. + if ((curEvent.recurrences != undefined) && (curEvent.recurrences[dateLookupKey] != undefined)) + { + // We found an override, so for this recurrence, use a potentially different title, start date, and duration. + curEvent = curEvent.recurrences[dateLookupKey]; + startDate = moment(curEvent.start); + curDuration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x")); + } + // If there's no recurrence override, check for an exception date. Exception dates represent exceptions to the rule. + else if ((curEvent.exdate != undefined) && (curEvent.exdate[dateLookupKey] != undefined)) + { + // This date is an exception date, which means we should skip it in the recurrence pattern. + showRecurrence = false; + } + + // Set the the title and the end date from either the regular event or the recurrence override. + var recurrenceTitle = curEvent.summary; + endDate = moment(parseInt(startDate.format("x")) + curDuration, 'x'); + + // If this recurrence ends before the start of the date range, or starts after the end of the date range, + // don't process it. + if (endDate.isBefore(rangeStart) || startDate.isAfter(rangeEnd)) { + showRecurrence = false; + } + + if (showRecurrence === true) { + + console.log('title:' + recurrenceTitle); + console.log('startDate:' + startDate.format('MMMM Do YYYY, h:mm:ss a')); + console.log('endDate:' + endDate.format('MMMM Do YYYY, h:mm:ss a')); + console.log('duration:' + moment.duration(curDuration).humanize()); + console.log(); + } + + } + } + } +} + + diff --git a/modules/default/calendar/vendor/ical.js/examples/example_rrule.ics b/modules/default/calendar/vendor/ical.js/examples/example_rrule.ics new file mode 100644 index 00000000..4f72c0ec --- /dev/null +++ b/modules/default/calendar/vendor/ical.js/examples/example_rrule.ics @@ -0,0 +1,40 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:ical +X-WR-TIMEZONE:US/Central +X-WR-CALDESC: +BEGIN:VEVENT +UID:98765432-ABCD-DCBB-999A-987765432123 +DTSTART;TZID=US/Central:20170601T090000 +DTEND;TZID=US/Central:20170601T170000 +DTSTAMP:20170727T044436Z +EXDATE;TZID=US/Central:20170706T090000,20170713T090000,20170720T090000,20 + 170803T090000 +LAST-MODIFIED:20170727T044435Z +RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20170814T045959Z;BYDAY=TH +SEQUENCE:0 +SUMMARY:Recurring weekly meeting from June 1 - Aug 14 (except July 6, July 13, July 20, Aug 3) +END:VEVENT +BEGIN:VEVENT +UID:98765432-ABCD-DCBB-999A-987765432123 +RECURRENCE-ID;TZID=US/Central:20170629T090000 +DTSTART;TZID=US/Central:20170703T090000 +DTEND;TZID=US/Central:20170703T120000 +DTSTAMP:20170727T044436Z +LAST-MODIFIED:20170216T143445Z +SEQUENCE:0 +SUMMARY:Last meeting in June moved to Monday July 3 and shortened to half day +END:VEVENT +BEGIN:VEVENT +UID:12354454-ABCD-DCBB-999A-2349872354897 +DTSTART;TZID=US/Central:20171201T130000 +DTEND;TZID=US/Central:20171201T150000 +DTSTAMP:20170727T044436Z +LAST-MODIFIED:20170727T044435Z +SEQUENCE:0 +SUMMARY:Single event on Dec 1 +END:VEVENT +END:VCALENDAR \ No newline at end of file diff --git a/modules/default/calendar/vendor/ical.js/node-ical.js b/modules/default/calendar/vendor/ical.js/node-ical.js index 1d295f8c..fd817bef 100644 --- a/modules/default/calendar/vendor/ical.js/node-ical.js +++ b/modules/default/calendar/vendor/ical.js/node-ical.js @@ -6,9 +6,16 @@ exports.fromURL = function(url, opts, cb){ if (!cb) return; request(url, opts, function(err, r, data){ - if (err) - return cb(err, null); - cb(undefined, ical.parseICS(data)); + if (err) + { + return cb(err, null); + } + else if (r.statusCode != 200) + { + return cb(r.statusCode + ": " + r.statusMessage, null); + } + + cb(undefined, ical.parseICS(data)); }) } @@ -17,44 +24,43 @@ exports.parseFile = function(filename){ } -var rrule = require('rrule-alt').RRule -var rrulestr = rrule.rrulestr +var rrule = require('rrule').RRule ical.objectHandlers['RRULE'] = function(val, params, curr, stack, line){ curr.rrule = line; return curr } var originalEnd = ical.objectHandlers['END']; -ical.objectHandlers['END'] = function(val, params, curr, stack){ - if (curr.rrule) { - var rule = curr.rrule; - if (rule.indexOf('DTSTART') === -1) { +ical.objectHandlers['END'] = function (val, params, curr, stack) { + // Recurrence rules are only valid for VEVENT, VTODO, and VJOURNAL. + // More specifically, we need to filter the VCALENDAR type because we might end up with a defined rrule + // due to the subtypes. + if ((val === "VEVENT") || (val === "VTODO") || (val === "VJOURNAL")) { + if (curr.rrule) { + var rule = curr.rrule.replace('RRULE:', ''); + if (rule.indexOf('DTSTART') === -1) { - if (curr.start.length === 8) { - var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(curr.start); - if (comps) { - curr.start = new Date (comps[1], comps[2] - 1, comps[3]); - } - } + if (curr.start.length === 8) { + var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(curr.start); + if (comps) { + curr.start = new Date(comps[1], comps[2] - 1, comps[3]); + } + } - if( typeof (curr.start) === "date") { - rule += ' DTSTART:' + curr.start.toISOString().replace(/[-:]/g, ''); - rule = rule.replace(/\.[0-9]{3}/, ''); - } - } - for (var i in curr.exdates) { - if( typeof (curr.exdates[i]) === "date") { - rule += ' EXDATE:' + curr.exdates[i].toISOString().replace(/[-:]/g, ''); - rule = rule.replace(/\.[0-9]{3}/, ''); - } - } - try { - curr.rrule = rrulestr(rule); - } - catch(err) { - console.log("Unrecognised element in calendar feed, ignoring: " + rule); - curr.rrule = null; - } - } + + if (typeof curr.start.toISOString === 'function') { + try { + rule += ';DTSTART=' + curr.start.toISOString().replace(/[-:]/g, ''); + rule = rule.replace(/\.[0-9]{3}/, ''); + } catch (error) { + console.error("ERROR when trying to convert to ISOString", error); + } + } else { + console.error("No toISOString function in curr.start", curr.start); + } + } + curr.rrule = rrule.fromString(rule); + } + } return originalEnd.call(this, val, params, curr, stack); } diff --git a/modules/default/calendar/vendor/ical.js/package.json b/modules/default/calendar/vendor/ical.js/package.json index 991b1440..0b226f6b 100644 --- a/modules/default/calendar/vendor/ical.js/package.json +++ b/modules/default/calendar/vendor/ical.js/package.json @@ -10,17 +10,18 @@ ], "homepage": "https://github.com/peterbraden/ical.js", "author": "Peter Braden (peterbraden.co.uk)", + "license": "Apache-2.0", "repository": { "type": "git", "url": "git://github.com/peterbraden/ical.js.git" }, "dependencies": { - "request": "2.68.0", - "rrule": "2.0.0" + "request": "^2.88.0", + "rrule": "2.4.1" }, "devDependencies": { - "vows": "0.7.0", - "underscore": "1.3.0" + "vows": "0.8.2", + "underscore": "1.9.1" }, "scripts": { "test": "./node_modules/vows/bin/vows ./test/test.js" diff --git a/modules/default/calendar/vendor/ical.js/readme.md b/modules/default/calendar/vendor/ical.js/readme.md index 2daba074..5f056436 100644 --- a/modules/default/calendar/vendor/ical.js/readme.md +++ b/modules/default/calendar/vendor/ical.js/readme.md @@ -7,6 +7,7 @@ A tolerant, minimal icalendar parser for javascript/node (http://tools.ietf.org/html/rfc5545) + ## Install - Node.js ## ical.js is availble on npm: @@ -33,19 +34,29 @@ Use the request library to fetch the specified URL (```opts``` gets passed on to ## Example 1 - Print list of upcoming node conferences (see example.js) ```javascript - var ical = require('ical') - , months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] +'use strict'; - ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, function(err, data) { - for (var k in data){ - if (data.hasOwnProperty(k)) { - var ev = data[k] - console.log("Conference", - ev.summary, - 'is in', - ev.location, - 'on the', ev.start.getDate(), 'of', months[ev.start.getMonth()]); - } - } - }); +const ical = require('ical'); +const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + +ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, function (err, data) { + for (let k in data) { + if (data.hasOwnProperty(k)) { + var ev = data[k]; + if (data[k].type == 'VEVENT') { + console.log(`${ev.summary} is in ${ev.location} on the ${ev.start.getDate()} of ${months[ev.start.getMonth()]} at ${ev.start.toLocaleTimeString('en-GB')}`); + + } + } + } +}); ``` + +## Recurrences and Exceptions ## +Calendar events with recurrence rules can be significantly more complicated to handle correctly. There are three parts to handling them: + + 1. rrule - the recurrence rule specifying the pattern of recurring dates and times for the event. + 2. recurrences - an optional array of event data that can override specific occurrences of the event. + 3. exdate - an optional array of dates that should be excluded from the recurrence pattern. + +See example_rrule.js for an example of handling recurring calendar events. diff --git a/modules/default/calendar/vendor/ical.js/test/test.js b/modules/default/calendar/vendor/ical.js/test/test.js index 041a4a13..ba6ad1a6 100644 --- a/modules/default/calendar/vendor/ical.js/test/test.js +++ b/modules/default/calendar/vendor/ical.js/test/test.js @@ -43,6 +43,12 @@ vows.describe('node-ical').addBatch({ , 'has a summary (invalid colon handling tolerance)' : function(topic){ assert.equal(topic.summary, '[Async]: Everything Express') } + , 'has a date only start datetime' : function(topic){ + assert.equal(topic.start.dateOnly, true) + } + , 'has a date only end datetime' : function(topic){ + assert.equal(topic.end.dateOnly, true) + } } , 'event d4c8' :{ topic : function(events){ @@ -108,7 +114,7 @@ vows.describe('node-ical').addBatch({ assert.equal(topic.end.getFullYear(), 1998); assert.equal(topic.end.getUTCMonth(), 2); assert.equal(topic.end.getUTCDate(), 15); - assert.equal(topic.end.getUTCHours(), 0); + assert.equal(topic.end.getUTCHours(), 00); assert.equal(topic.end.getUTCMinutes(), 30); } } @@ -146,7 +152,7 @@ vows.describe('node-ical').addBatch({ } , 'has a start datetime' : function(topic) { assert.equal(topic.start.getFullYear(), 2011); - assert.equal(topic.start.getMonth(), 9); + assert.equal(topic.start.getMonth(), 09); assert.equal(topic.start.getDate(), 11); } @@ -192,12 +198,12 @@ vows.describe('node-ical').addBatch({ } , 'has a start' : function(topic){ assert.equal(topic.start.tz, 'America/Phoenix') - assert.equal(topic.start.toISOString(), new Date(2011, 10, 9, 19, 0,0).toISOString()) + assert.equal(topic.start.toISOString(), new Date(2011, 10, 09, 19, 0,0).toISOString()) } } } - , 'with test6.ics (testing assembly.org)' : { + , 'with test6.ics (testing assembly.org)': { topic: function () { return ical.parseFile('./test/test6.ics') } @@ -208,7 +214,7 @@ vows.describe('node-ical').addBatch({ })[0]; } , 'has a start' : function(topic){ - assert.equal(topic.start.toISOString(), new Date(2011, 7, 4, 12, 0,0).toISOString()) + assert.equal(topic.start.toISOString(), new Date(2011, 07, 04, 12, 0,0).toISOString()) } } , 'event with rrule' :{ @@ -249,7 +255,7 @@ vows.describe('node-ical').addBatch({ }, 'task completed': function(task){ assert.equal(task.completion, 100); - assert.equal(task.completed.toISOString(), new Date(2013, 6, 16, 10, 57, 45).toISOString()); + assert.equal(task.completed.toISOString(), new Date(2013, 06, 16, 10, 57, 45).toISOString()); } } } @@ -367,14 +373,115 @@ vows.describe('node-ical').addBatch({ assert.equal(topic.end.getFullYear(), 2014); assert.equal(topic.end.getMonth(), 3); assert.equal(topic.end.getUTCHours(), 19); - assert.equal(topic.end.getUTCMinutes(), 0); + assert.equal(topic.end.getUTCMinutes(), 00); } } - }, + } - 'url request errors' : { + , 'with test12.ics (testing recurrences and exdates)': { + topic: function () { + return ical.parseFile('./test/test12.ics') + } + , 'event with rrule': { + topic: function (events) { + return _.select(_.values(events), function (x) { + return x.uid === '0000001'; + })[0]; + } + , "Has an RRULE": function (topic) { + assert.notEqual(topic.rrule, undefined); + } + , "Has summary Treasure Hunting": function (topic) { + assert.equal(topic.summary, 'Treasure Hunting'); + } + , "Has two EXDATES": function (topic) { + assert.notEqual(topic.exdate, undefined); + assert.notEqual(topic.exdate[new Date(2015, 06, 08, 12, 0, 0).toISOString().substring(0, 10)], undefined); + assert.notEqual(topic.exdate[new Date(2015, 06, 10, 12, 0, 0).toISOString().substring(0, 10)], undefined); + } + , "Has a RECURRENCE-ID override": function (topic) { + assert.notEqual(topic.recurrences, undefined); + assert.notEqual(topic.recurrences[new Date(2015, 06, 07, 12, 0, 0).toISOString().substring(0, 10)], undefined); + assert.equal(topic.recurrences[new Date(2015, 06, 07, 12, 0, 0).toISOString().substring(0, 10)].summary, 'More Treasure Hunting'); + } + } + } + + , 'with test13.ics (testing recurrence-id before rrule)': { + topic: function () { + return ical.parseFile('./test/test13.ics') + } + , 'event with rrule': { + topic: function (events) { + return _.select(_.values(events), function (x) { + return x.uid === '6m2q7kb2l02798oagemrcgm6pk@google.com'; + })[0]; + } + , "Has an RRULE": function (topic) { + assert.notEqual(topic.rrule, undefined); + } + , "Has summary 'repeated'": function (topic) { + assert.equal(topic.summary, 'repeated'); + } + , "Has a RECURRENCE-ID override": function (topic) { + assert.notEqual(topic.recurrences, undefined); + assert.notEqual(topic.recurrences[new Date(2016, 7, 26, 14, 0, 0).toISOString().substring(0, 10)], undefined); + assert.equal(topic.recurrences[new Date(2016, 7, 26, 14, 0, 0).toISOString().substring(0, 10)].summary, 'bla bla'); + } + } + } + + , 'with test14.ics (testing comma-separated exdates)': { + topic: function () { + return ical.parseFile('./test/test14.ics') + } + , 'event with comma-separated exdate': { + topic: function (events) { + return _.select(_.values(events), function (x) { + return x.uid === '98765432-ABCD-DCBB-999A-987765432123'; + })[0]; + } + , "Has summary 'Example of comma-separated exdates'": function (topic) { + assert.equal(topic.summary, 'Example of comma-separated exdates'); + } + , "Has four comma-separated EXDATES": function (topic) { + assert.notEqual(topic.exdate, undefined); + // Verify the four comma-separated EXDATES are there + assert.notEqual(topic.exdate[new Date(2017, 6, 6, 12, 0, 0).toISOString().substring(0, 10)], undefined); + assert.notEqual(topic.exdate[new Date(2017, 6, 17, 12, 0, 0).toISOString().substring(0, 10)], undefined); + assert.notEqual(topic.exdate[new Date(2017, 6, 20, 12, 0, 0).toISOString().substring(0, 10)], undefined); + assert.notEqual(topic.exdate[new Date(2017, 7, 3, 12, 0, 0).toISOString().substring(0, 10)], undefined); + // Verify an arbitrary date isn't there + assert.equal(topic.exdate[new Date(2017, 4, 5, 12, 0, 0).toISOString().substring(0, 10)], undefined); + } + } + } + + , 'with test14.ics (testing exdates with bad times)': { + topic: function () { + return ical.parseFile('./test/test14.ics') + } + , 'event with exdates with bad times': { + topic: function (events) { + return _.select(_.values(events), function (x) { + return x.uid === '1234567-ABCD-ABCD-ABCD-123456789012'; + })[0]; + } + , "Has summary 'Example of exdate with bad times'": function (topic) { + assert.equal(topic.summary, 'Example of exdate with bad times'); + } + , "Has two EXDATES even though they have bad times": function (topic) { + assert.notEqual(topic.exdate, undefined); + // Verify the two EXDATES are there, even though they have bad times + assert.notEqual(topic.exdate[new Date(2017, 11, 18, 12, 0, 0).toISOString().substring(0, 10)], undefined); + assert.notEqual(topic.exdate[new Date(2017, 11, 19, 12, 0, 0).toISOString().substring(0, 10)], undefined); + } + } + } + + , 'url request errors': { topic : function () { - ical.fromURL('http://not.exist/', {}, this.callback); + ical.fromURL('http://255.255.255.255/', {}, this.callback); } , 'are passed back to the callback' : function (err, result) { assert.instanceOf(err, Error); diff --git a/modules/default/calendar/vendor/ical.js/test/test12.ics b/modules/default/calendar/vendor/ical.js/test/test12.ics new file mode 100644 index 00000000..4e78603b --- /dev/null +++ b/modules/default/calendar/vendor/ical.js/test/test12.ics @@ -0,0 +1,19 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +UID:0000001 +SUMMARY:Treasure Hunting +DTSTART;TZID=America/Los_Angeles:20150706T120000 +DTEND;TZID=America/Los_Angeles:20150706T130000 +RRULE:FREQ=DAILY;COUNT=10 +EXDATE;TZID=America/Los_Angeles:20150708T120000 +EXDATE;TZID=America/Los_Angeles:20150710T120000 +END:VEVENT +BEGIN:VEVENT +UID:0000001 +SUMMARY:More Treasure Hunting +LOCATION:The other island +DTSTART;TZID=America/Los_Angeles:20150709T150000 +DTEND;TZID=America/Los_Angeles:20150707T160000 +RECURRENCE-ID;TZID=America/Los_Angeles:20150707T120000 +END:VEVENT +END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test13.ics b/modules/default/calendar/vendor/ical.js/test/test13.ics new file mode 100644 index 00000000..3118186b --- /dev/null +++ b/modules/default/calendar/vendor/ical.js/test/test13.ics @@ -0,0 +1,57 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:ical +X-WR-TIMEZONE:Europe/Kiev +X-WR-CALDESC: +BEGIN:VTIMEZONE +TZID:Europe/Kiev +X-LIC-LOCATION:Europe/Kiev +BEGIN:DAYLIGHT +TZOFFSETFROM:+0200 +TZOFFSETTO:+0300 +TZNAME:EEST +DTSTART:19700329T030000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0300 +TZOFFSETTO:+0200 +TZNAME:EET +DTSTART:19701025T040000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTART;TZID=Europe/Kiev:20160826T140000 +DTEND;TZID=Europe/Kiev:20160826T150000 +DTSTAMP:20160825T061505Z +UID:6m2q7kb2l02798oagemrcgm6pk@google.com +RECURRENCE-ID;TZID=Europe/Kiev:20160826T140000 +CREATED:20160823T125221Z +DESCRIPTION: +LAST-MODIFIED:20160823T130320Z +LOCATION: +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:bla bla +TRANSP:OPAQUE +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=Europe/Kiev:20160825T140000 +DTEND;TZID=Europe/Kiev:20160825T150000 +RRULE:FREQ=DAILY;UNTIL=20160828T110000Z +DTSTAMP:20160825T061505Z +UID:6m2q7kb2l02798oagemrcgm6pk@google.com +CREATED:20160823T125221Z +DESCRIPTION: +LAST-MODIFIED:20160823T125221Z +LOCATION: +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:repeated +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR \ No newline at end of file diff --git a/modules/default/calendar/vendor/ical.js/test/test14.ics b/modules/default/calendar/vendor/ical.js/test/test14.ics new file mode 100644 index 00000000..5c4f5caf --- /dev/null +++ b/modules/default/calendar/vendor/ical.js/test/test14.ics @@ -0,0 +1,33 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:ical +X-WR-TIMEZONE:Europe/Kiev +X-WR-CALDESC: +BEGIN:VEVENT +UID:98765432-ABCD-DCBB-999A-987765432123 +DTSTART;TZID=US/Central:20170216T090000 +DTEND;TZID=US/Central:20170216T190000 +DTSTAMP:20170727T044436Z +EXDATE;TZID=US/Central:20170706T090000,20170717T090000,20170720T090000,20 + 170803T090000 +LAST-MODIFIED:20170727T044435Z +RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20170814T045959Z;INTERVAL=2;BYDAY=MO,TH +SEQUENCE:0 +SUMMARY:Example of comma-separated exdates +END:VEVENT +BEGIN:VEVENT +UID:1234567-ABCD-ABCD-ABCD-123456789012 +DTSTART:20170814T140000Z +DTEND:20170815T000000Z +DTSTAMP:20171204T134925Z +EXDATE:20171219T060000 +EXDATE:20171218T060000 +LAST-MODIFIED:20171024T140004Z +RRULE:FREQ=WEEKLY;WKST=SU;INTERVAL=2;BYDAY=MO,TU +SEQUENCE:0 +SUMMARY:Example of exdate with bad times +END:VEVENT +END:VCALENDAR \ No newline at end of file From e56f61441db25ac204d44048c2cb185a13f03dca Mon Sep 17 00:00:00 2001 From: Matt Bauer Date: Thu, 13 Jun 2019 12:46:10 -0500 Subject: [PATCH 2/5] =?UTF-8?q?Repeating=20event=20handling=20=E2=80=9Crob?= =?UTF-8?q?ustified=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + modules/default/calendar/calendarfetcher.js | 114 +++++++++++++++++--- 2 files changed, 101 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbd6a70e..82c13f7c 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ Added UK Met Office Datapoint feed as a provider in the default weather module. - Allowance HTML5 autoplay-policy (policy is changed from Chrome 66 updates) - Handle SIGTERM messages - Fixes sliceMultiDayEvents so it respects maximumNumberOfDays +- Fixed issues with calendar not displaying one-time changes to repeating events >>>>>>> upstream/develop ## [2.7.1] - 2019-04-02 diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 3a30aea2..434cea8a 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -63,7 +63,8 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri // console.log(data); newEvents = []; - var limitFunction = function(date, i) {return i < maximumEntries;}; + // limitFunction doesn't do much limiting, see comment re: the dates array in rrule section below as to why we need to do the filtering ourselves + var limitFunction = function(date, i) {return true;}; var eventDate = function(event, time) { return (event[time].length === 8) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); @@ -115,12 +116,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri startDate = startDate.startOf("day"); } - var title = "Event"; - if (event.summary) { - title = (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary; - } else if(event.description) { - title = event.description; - } + var title = getTitleFromEvent(event); var excluded = false, dateFilter = null; @@ -176,8 +172,10 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri var geo = event.geo || false; var description = event.description || false; + // Begin recurring event parsing if (typeof event.rrule != "undefined" && event.rrule != null && !isFacebookBirthday) { var rule = event.rrule; + var addedEvents = 0; // can cause problems with e.g. birthdays before 1900 if(rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900 || @@ -186,19 +184,88 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri rule.options.dtstart.setYear(1900); } + // For recurring events, get the set of start dates that fall within the range + // of dates we"re looking for. var dates = rule.between(past, future, true, limitFunction); - for (var d in dates) { - startDate = moment(new Date(dates[d])); - endDate = moment(parseInt(startDate.format("x")) + duration, "x"); + // The "dates" array contains the set of dates within our desired date range range that are valid + // for the recurrence rule. *However*, it"s possible for us to have a specific recurrence that + // had its date changed from outside the range to inside the range. For the time being, + // we"ll handle this by adding *all* recurrence entries into the set of dates that we check, + // because the logic below will filter out any recurrences that don"t actually belong within + // our display range. + // Would be great if there was a better way to handle this. + if (event.recurrences != undefined) + { + var pastMoment = moment(past); + var futureMoment = moment(future); - if (timeFilterApplies(now, endDate, dateFilter)) { - continue; + for (var r in event.recurrences) + { + // Only add dates that weren't already in the range we added from the rrule so that + // we don"t double-add those events. + if (moment(new Date(r)).isBetween(pastMoment, futureMoment) != true) + { + dates.push(new Date(r)); + } + } + } + + + // Loop through the set of date entries to see which recurrences should be added to our event list. + for (var d in dates) { + var date = dates[d]; + // ical.js started returning recurrences and exdates as ISOStrings without time information. + // .toISOString().substring(0,10) is the method they use to calculate keys, so we'll do the same + // (see https://github.com/peterbraden/ical.js/pull/84 ) + var dateKey = date.toISOString().substring(0,10); + var curEvent = event; + var showRecurrence = true; + + // Stop parsing this event's recurrences if we've already found maximumEntries worth of recurrences. + // (The logic below would still filter the extras, but the check is simple since we're already tracking the count) + if (addedEvents >= maximumEntries) { + break; } - if (includePastEvents || endDate.format("x") > now) { + startDate = moment(date); + + // For each date that we"re checking, it"s possible that there is a recurrence override for that one day. + if ((curEvent.recurrences != undefined) && (curEvent.recurrences[dateKey] != undefined)) + { + // We found an override, so for this recurrence, use a potentially different title, start date, and duration. + curEvent = curEvent.recurrences[dateKey]; + startDate = moment(curEvent.start); + duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x")); + } + // If there"s no recurrence override, check for an exception date. Exception dates represent exceptions to the rule. + else if ((curEvent.exdate != undefined) && (curEvent.exdate[dateKey] != undefined)) + { + // This date is an exception date, which means we should skip it in the recurrence pattern. + showRecurrence = false; + } + + endDate = moment(parseInt(startDate.format("x")) + duration, "x"); + if (startDate.format("x") == endDate.format("x")) { + endDate = endDate.endOf("day") + } + + var recurrenceTitle = getTitleFromEvent(curEvent); + + // If this recurrence ends before the start of the date range, or starts after the end of the date range, don"t add + // it to the event list. + if (endDate.isBefore(past) || startDate.isAfter(future)) { + showRecurrence = false; + } + + if (timeFilterApplies(now, endDate, dateFilter)) { + showRecurrence = false; + } + + if ((showRecurrence === true) && (addedEvents < maximumEntries)) { + addedEvents++; newEvents.push({ - title: title, + title: recurrenceTitle, startDate: startDate.format("x"), endDate: endDate.format("x"), fullDayEvent: isFullDayEvent(event), @@ -210,6 +277,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri }); } } + // end recurring event parsing } else { // console.log("Single event ..."); // Single event. @@ -327,6 +395,24 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri return false; }; + /* getTitleFromEvent(event) + * Gets the title from the event. + * + * argument event object - The event object to check. + * + * return string - The title of the event, or "Event" if no title is found. + */ + var getTitleFromEvent = function (event) { + var title = "Event"; + if (event.summary) { + title = (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary; + } else if (event.description) { + title = event.description; + } + + return title; + }; + var testTitleByFilter = function (title, filter, useRegex, regexFlags) { if (useRegex) { // Assume if leading slash, there is also trailing slash From a6284e05e5eece8c2878d09d3e044e8e470c7d07 Mon Sep 17 00:00:00 2001 From: Matt Bauer Date: Thu, 13 Jun 2019 14:42:21 -0500 Subject: [PATCH 3/5] =?UTF-8?q?Update=20rrule=20and=20request=20dependenci?= =?UTF-8?q?es=20for=20calendar=E2=80=99s=20vendored=20ical.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rrule-alt has not been updated in some time, while the main rrule has. ical.js is using updated rrule. Getting rid of rrule-alt would affect some third-party modules, however, so we should keep it around for now at least. --- package-lock.json | 402 ++++++++++++++++++--------------------- package.json | 3 +- vendor/package-lock.json | 41 ++-- 3 files changed, 198 insertions(+), 248 deletions(-) diff --git a/package-lock.json b/package-lock.json index ad622926..5c6210a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -698,9 +698,12 @@ "dev": true }, "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } }, "assert-plus": { "version": "1.0.0", @@ -767,9 +770,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "babel-polyfill": { "version": "6.26.0", @@ -905,7 +908,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "optional": true, "requires": { "tweetnacl": "^0.14.3" } @@ -1184,9 +1186,9 @@ "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" }, "callsites": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", - "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { @@ -1377,11 +1379,6 @@ "is-supported-regexp-flag": "^1.0.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1430,9 +1427,9 @@ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } @@ -2153,12 +2150,12 @@ } }, "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "requires": { - "jsbn": "~0.1.0" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, "ee-first": { @@ -2518,12 +2515,6 @@ "ms": "^2.1.1" } }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, "file-entry-cache": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", @@ -2533,17 +2524,6 @@ "flat-cache": "^2.0.1" } }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2556,18 +2536,6 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", @@ -2575,81 +2543,17 @@ "dev": true }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2667,27 +2571,6 @@ "requires": { "has-flag": "^3.0.0" } - }, - "table": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", - "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", - "dev": true, - "requires": { - "ajv": "^6.9.1", - "lodash": "^4.17.11", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - } - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } } } }, @@ -2994,7 +2877,8 @@ "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true }, "extend-shallow": { "version": "2.0.1", @@ -3089,9 +2973,10 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true }, "fast-glob": { "version": "2.2.6", @@ -3233,12 +3118,12 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "1.0.6", + "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, @@ -3611,13 +3496,13 @@ } }, "grunt-eslint": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-21.0.0.tgz", - "integrity": "sha512-HJocD9P35lpCvy6pPPCTgzBavzckrT1nt7lpqV55Vy8E6LQJv4RortXoH1jJTYhO5DYY7RPATv7Uc4383PUYqQ==", + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-21.1.0.tgz", + "integrity": "sha512-TN1C4BV947eUB/XrROUQ/QFTufWgH6wdfaxhlfmpjE70bFTp5q+Q2LgIZ5Y//+Rn1BWrXmm44sxegijNN6WR/A==", "dev": true, "requires": { "chalk": "^2.1.0", - "eslint": "^5.0.0" + "eslint": "^5.16.0" }, "dependencies": { "ansi-styles": { @@ -3803,12 +3688,49 @@ } }, "grunt-stylelint": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/grunt-stylelint/-/grunt-stylelint-0.10.1.tgz", - "integrity": "sha512-7MAHUqySn2x0yCS4SEkrv5pVoTrP44j8IZGEF6UTQD9Nm7K96cGEhB6FFMWk+uXbRHiiU+c4s3B0h4rpT8nOyQ==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/grunt-stylelint/-/grunt-stylelint-0.11.0.tgz", + "integrity": "sha512-/6LOPh8ftRS70tKa676ZrGG+eNCQQHJPH5QWe4gmzdW+K3Ud0YwbmUe1Bly3x9ymfllNTCALRmMJoV9xEh9RFA==", "dev": true, "requires": { - "chalk": "1.1.3" + "chalk": "2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "grunt-yamllint": { @@ -3845,25 +3767,12 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "requires": { - "ajv": "^5.1.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - } } }, "has-ansi": { @@ -4172,9 +4081,9 @@ "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" }, "inquirer": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", - "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", + "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", "dev": true, "requires": { "ansi-escapes": "^3.2.0", @@ -4188,7 +4097,7 @@ "run-async": "^2.2.0", "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^5.0.0", + "strip-ansi": "^5.1.0", "through": "^2.3.6" }, "dependencies": { @@ -4619,8 +4528,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsdom": { "version": "11.6.2", @@ -4800,9 +4708,10 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -5087,6 +4996,12 @@ "signal-exit": "^3.0.0" } }, + "luxon": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.16.0.tgz", + "integrity": "sha512-qaqB+JwpGwtl7UbIXng3A/l4W/ySBr8drQvwtMLZBMiLD2V+0fEnPWMrs+UjnIy9PsktazQaKvwDUCLzoWz0Hw==", + "optional": true + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -5649,9 +5564,9 @@ "dev": true }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", @@ -6340,6 +6255,11 @@ "through2": "~0.2.3" } }, + "psl": { + "version": "1.1.32", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", + "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==" + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -6598,30 +6518,69 @@ "dev": true }, "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "uuid": "^3.3.2" + }, + "dependencies": { + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } } }, "request-promise-core": { @@ -6735,6 +6694,15 @@ } } }, + "rrule": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.6.2.tgz", + "integrity": "sha512-xL38CM1zOYOIp4OO8hdD6zHH5UdR9siHMvPiv+CCSh7o0LYJ0owg87QcFW7GXJ0PfpLBHjanEMvvBjJxbRhAcQ==", + "requires": { + "luxon": "^1.3.3", + "tslib": "^1.9.0" + } + }, "rrule-alt": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/rrule-alt/-/rrule-alt-2.2.8.tgz", @@ -6765,9 +6733,9 @@ } }, "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -7215,9 +7183,9 @@ "dev": true }, "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -7639,18 +7607,18 @@ } }, "stylelint-config-recommended": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz", - "integrity": "sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-2.2.0.tgz", + "integrity": "sha512-bZ+d4RiNEfmoR74KZtCKmsABdBJr4iXRiCso+6LtMJPw5rd/KnxUWTxht7TbafrTJK1YRjNgnN0iVZaJfc3xJA==", "dev": true }, "stylelint-config-standard": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-18.2.0.tgz", - "integrity": "sha512-07x0TaSIzvXlbOioUU4ORkCIM07kyIuojkbSVCyFWNVgXMXYHfhnQSCkqu+oHWJf3YADAnPGWzdJ53NxkoJ7RA==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-18.3.0.tgz", + "integrity": "sha512-Tdc/TFeddjjy64LvjPau9SsfVRexmTFqUhnMBrzz07J4p2dVQtmpncRF/o8yZn8ugA3Ut43E6o1GtjX80TFytw==", "dev": true, "requires": { - "stylelint-config-recommended": "^2.1.0" + "stylelint-config-recommended": "^2.2.0" } }, "sugarss": { @@ -7996,6 +7964,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, "requires": { "punycode": "^1.4.1" } @@ -8049,8 +8018,7 @@ "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tunnel-agent": { "version": "0.6.0", @@ -8063,8 +8031,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { "version": "0.3.2", @@ -8351,7 +8318,8 @@ "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true }, "valid-url": { "version": "1.0.9", diff --git a/package.json b/package.json index a0a27ffe..f76a54d9 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "iconv-lite": "latest", "mocha-logger": "^1.0.6", "moment": "latest", - "request": "^2.87.0", + "request": "^2.88.0", + "rrule": "^2.6.2", "rrule-alt": "^2.2.8", "simple-git": "^1.85.0", "socket.io": "^2.1.1", diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 61c1d19e..795e7b00 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -225,8 +225,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -244,13 +243,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -263,18 +260,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -377,8 +371,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -388,7 +381,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -401,20 +393,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.2.4", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -431,7 +420,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -504,8 +492,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -515,7 +502,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -591,8 +577,7 @@ }, "safe-buffer": { "version": "5.1.1", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -622,7 +607,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -640,7 +624,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -679,13 +662,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.2", - "bundled": true, - "optional": true + "bundled": true } } }, From d41afa0e532e076b57a191649bd13868c0e5c026 Mon Sep 17 00:00:00 2001 From: Matt Bauer Date: Thu, 13 Jun 2019 15:52:49 -0500 Subject: [PATCH 4/5] Calendar fetch error is still a loading result Also log error on node side as well. --- modules/default/calendar/calendar.js | 1 + modules/default/calendar/node_helper.js | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 2eac086e..7da5efd0 100755 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -135,6 +135,7 @@ Module.register("calendar", { } } else if (notification === "FETCH_ERROR") { Log.error("Calendar Error. Could not fetch calendar: " + payload.url); + this.loaded = true } else if (notification === "INCORRECT_URL") { Log.error("Calendar Error. Incorrect url: " + payload.url); } else { diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index 9c6e4979..7d644ace 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -60,6 +60,7 @@ module.exports = NodeHelper.create({ }); fetcher.onError(function(fetcher, error) { + console.error("Calendar Error. Could not fetch calendar: ", fetcher.url(), error) self.sendSocketNotification("FETCH_ERROR", { url: fetcher.url(), error: error From 808cbf8e0be19eff971eefaefad2810b3895f9fd Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Fri, 14 Jun 2019 13:32:07 +0200 Subject: [PATCH 5/5] Fix Typecheck. --- modules/default/calendar/calendarfetcher.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index ad5b4daa..cb2f5979 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -171,12 +171,13 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri var geo = event.geo || false; var description = event.description || false; - if (typeof event.rrule !== undefined && event.rrule !== null && !isFacebookBirthday) { + + if (typeof event.rrule !== 'undefined' && event.rrule !== null && !isFacebookBirthday) { var rule = event.rrule; var addedEvents = 0; // can cause problems with e.g. birthdays before 1900 - if(rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900 || + if(rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900 || rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900){ rule.origOptions.dtstart.setYear(1900); rule.options.dtstart.setYear(1900);