From 6d60baa2d61deb43aed0769b0527b9475f725064 Mon Sep 17 00:00:00 2001 From: rejas Date: Wed, 17 Jun 2020 21:17:26 +0200 Subject: [PATCH 01/11] Install latest ical version and use it --- modules/default/calendar/calendarfetcher.js | 509 ++++++++++---------- package-lock.json | 21 +- package.json | 2 + 3 files changed, 275 insertions(+), 257 deletions(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 45338fffdf..7871312a27 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -5,7 +5,8 @@ * MIT Licensed. */ const Log = require("../../../js/logger.js"); -const ical = require("./vendor/ical.js"); +const fetch = require("node-fetch"); +const ical = require("ical"); const moment = require("moment"); var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) { @@ -20,318 +21,316 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntr /* fetchCalendar() * Initiates calendar fetch. */ - var fetchCalendar = function () { + const fetchCalendar = function () { clearTimeout(reloadTimer); reloadTimer = null; - var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); - var opts = { + const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); + const opts = { headers: { "User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (/~https://github.com/MichMich/MagicMirror/)" }, - gzip: true + compress: true }; if (auth) { if (auth.method === "bearer") { - opts.auth = { - bearer: auth.pass - }; + opts.headers.Authorization = `Bearer ${auth.pass}`; } else { - opts.auth = { - user: auth.user, - pass: auth.pass - }; + let base64data = Buffer.from(`${auth.user}:${auth.pass}`).toString("base64"); + opts.headers.Authorization = `Basic ${base64data}`; + // TODO if (auth.method === "digest") { - opts.auth.sendImmediately = false; - } else { - opts.auth.sendImmediately = true; + //opts.auth.sendImmediately = false; } } } - ical.fromURL(url, opts, function (err, data) { - if (err) { - fetchFailedCallback(self, err); - scheduleTimer(); - return; - } - - var newEvents = []; - - // 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])); - }; + fetch(url, opts) + .then((response) => response.text()) + .then((rawData) => { + const data = ical.parseICS(rawData); + const newEvents = []; - for (var e in data) { - var event = data[e]; - var now = new Date(); - var today = moment().startOf("day").toDate(); - var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. - var past = today; + // 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 + const limitFunction = function (date, i) { + return true; + }; - if (includePastEvents) { - past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); - } + const eventDate = function (event, time) { + return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); + }; - // FIXME: Ugly fix to solve the facebook birthday issue. - // Otherwise, the recurring events only show the birthday for next year. - var isFacebookBirthday = false; - if (typeof event.uid !== "undefined") { - if (event.uid.indexOf("@facebook.com") !== -1) { - isFacebookBirthday = true; - } - } + for (let k in data) { + if (data.hasOwnProperty(k)) { + var event = data[k]; + var now = new Date(); + var today = moment().startOf("day").toDate(); + var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. + var past = today; - if (event.type === "VEVENT") { - var startDate = eventDate(event, "start"); - var endDate; - if (typeof event.end !== "undefined") { - endDate = eventDate(event, "end"); - } else if (typeof event.duration !== "undefined") { - var dur = moment.duration(event.duration); - endDate = startDate.clone().add(dur); - } else { - if (!isFacebookBirthday) { - endDate = startDate; - } else { - endDate = moment(startDate).add(1, "days"); + if (includePastEvents) { + past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); } - } - - // calculate the duration f the event for use with recurring events. - var duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); - - if (event.start.length === 8) { - startDate = startDate.startOf("day"); - } - - var title = getTitleFromEvent(event); - var excluded = false, - dateFilter = null; - - for (var f in excludedEvents) { - var filter = excludedEvents[f], - testTitle = title.toLowerCase(), - until = null, - useRegex = false, - regexFlags = "g"; - - if (filter instanceof Object) { - if (typeof filter.until !== "undefined") { - until = filter.until; - } - - if (typeof filter.regex !== "undefined") { - useRegex = filter.regex; - } - - // If additional advanced filtering is added in, this section - // must remain last as we overwrite the filter object with the - // filterBy string - if (filter.caseSensitive) { - filter = filter.filterBy; - testTitle = title; - } else if (useRegex) { - filter = filter.filterBy; - testTitle = title; - regexFlags += "i"; - } else { - filter = filter.filterBy.toLowerCase(); + // FIXME: Ugly fix to solve the facebook birthday issue. + // Otherwise, the recurring events only show the birthday for next year. + var isFacebookBirthday = false; + if (typeof event.uid !== "undefined") { + if (event.uid.indexOf("@facebook.com") !== -1) { + isFacebookBirthday = true; } - } else { - filter = filter.toLowerCase(); } - if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) { - if (until) { - dateFilter = until; + if (event.type === "VEVENT") { + var startDate = eventDate(event, "start"); + var endDate; + if (typeof event.end !== "undefined") { + endDate = eventDate(event, "end"); + } else if (typeof event.duration !== "undefined") { + var dur = moment.duration(event.duration); + endDate = startDate.clone().add(dur); } else { - excluded = true; + if (!isFacebookBirthday) { + endDate = startDate; + } else { + endDate = moment(startDate).add(1, "days"); + } } - break; - } - } - if (excluded) { - continue; - } - - var location = event.location || false; - var geo = event.geo || false; - var description = event.description || false; + // calculate the duration f the event for use with recurring events. + var duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); - if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { - var rule = event.rrule; - var addedEvents = 0; + if (event.start.length === 8) { + startDate = startDate.startOf("day"); + } - // can cause problems with e.g. birthdays before 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); - } + var title = getTitleFromEvent(event); + + var excluded = false, + dateFilter = null; + + for (var f in excludedEvents) { + var filter = excludedEvents[f], + testTitle = title.toLowerCase(), + until = null, + useRegex = false, + regexFlags = "g"; + + if (filter instanceof Object) { + if (typeof filter.until !== "undefined") { + until = filter.until; + } + + if (typeof filter.regex !== "undefined") { + useRegex = filter.regex; + } + + // If additional advanced filtering is added in, this section + // must remain last as we overwrite the filter object with the + // filterBy string + if (filter.caseSensitive) { + filter = filter.filterBy; + testTitle = title; + } else if (useRegex) { + filter = filter.filterBy; + testTitle = title; + regexFlags += "i"; + } else { + filter = filter.filterBy.toLowerCase(); + } + } else { + filter = filter.toLowerCase(); + } - // For recurring events, get the set of start dates that fall within the range - // of dates we"re looking for. - // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time - var pastLocal = moment(past).subtract(past.getTimezoneOffset(), "minutes").toDate(); - var futureLocal = moment(future).subtract(future.getTimezoneOffset(), "minutes").toDate(); - var datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); - var dates = datesLocal.map(function (dateLocal) { - var date = moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); - return date; - }); - - // 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); - - 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)); + if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) { + if (until) { + dateFilter = until; + } else { + excluded = true; + } + break; } } - } - // 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 (excluded) { + continue; } - startDate = moment(date); + var location = event.location || false; + var geo = event.geo || false; + var description = event.description || false; - // 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; - } + if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { + var rule = event.rrule; + var addedEvents = 0; - endDate = moment(parseInt(startDate.format("x")) + duration, "x"); - if (startDate.format("x") === endDate.format("x")) { - endDate = endDate.endOf("day"); - } + // can cause problems with e.g. birthdays before 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); + } - var recurrenceTitle = getTitleFromEvent(curEvent); + // For recurring events, get the set of start dates that fall within the range + // of dates we"re looking for. + // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time + var pastLocal = moment(past).subtract(past.getTimezoneOffset(), "minutes").toDate(); + var futureLocal = moment(future).subtract(future.getTimezoneOffset(), "minutes").toDate(); + var datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); + var dates = datesLocal.map(function (dateLocal) { + var date = moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); + return date; + }); - // 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; - } + // 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); + + 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)); + } + } + } - if (timeFilterApplies(now, endDate, dateFilter)) { - showRecurrence = false; - } + // 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; + } + + 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: recurrenceTitle, + startDate: startDate.format("x"), + endDate: endDate.format("x"), + fullDayEvent: isFullDayEvent(event), + class: event.class, + firstYear: event.start.getFullYear(), + location: location, + geo: geo, + description: description + }); + } + } + // end recurring event parsing + } else { + // Single event. + var fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); + + if (includePastEvents) { + // Past event is too far in the past, so skip. + if (endDate < past) { + continue; + } + } else { + // It's not a fullday event, and it is in the past, so skip. + if (!fullDayEvent && endDate < new Date()) { + continue; + } + + // It's a fullday event, and it is before today, So skip. + if (fullDayEvent && endDate <= today) { + continue; + } + } - if (showRecurrence === true && addedEvents < maximumEntries) { - addedEvents++; + // It exceeds the maximumNumberOfDays limit, so skip. + if (startDate > future) { + continue; + } + + if (timeFilterApplies(now, endDate, dateFilter)) { + continue; + } + + // Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already + if (fullDayEvent && startDate <= today) { + startDate = moment(today); + } + + // Every thing is good. Add it to the list. newEvents.push({ - title: recurrenceTitle, + title: title, startDate: startDate.format("x"), endDate: endDate.format("x"), - fullDayEvent: isFullDayEvent(event), + fullDayEvent: fullDayEvent, class: event.class, - firstYear: event.start.getFullYear(), location: location, geo: geo, description: description }); } } - // end recurring event parsing - } else { - // Single event. - var fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); - - if (includePastEvents) { - // Past event is too far in the past, so skip. - if (endDate < past) { - continue; - } - } else { - // It's not a fullday event, and it is in the past, so skip. - if (!fullDayEvent && endDate < new Date()) { - continue; - } - - // It's a fullday event, and it is before today, So skip. - if (fullDayEvent && endDate <= today) { - continue; - } - } - - // It exceeds the maximumNumberOfDays limit, so skip. - if (startDate > future) { - continue; - } - - if (timeFilterApplies(now, endDate, dateFilter)) { - continue; - } - - // Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already - if (fullDayEvent && startDate <= today) { - startDate = moment(today); - } - - // Every thing is good. Add it to the list. - newEvents.push({ - title: title, - startDate: startDate.format("x"), - endDate: endDate.format("x"), - fullDayEvent: fullDayEvent, - class: event.class, - location: location, - geo: geo, - description: description - }); } } - } - newEvents.sort(function (a, b) { - return a.startDate - b.startDate; - }); + newEvents.sort(function (a, b) { + return a.startDate - b.startDate; + }); - events = newEvents.slice(0, maximumEntries); + events = newEvents.slice(0, maximumEntries); - self.broadcastEvents(); - scheduleTimer(); - }); + self.broadcastEvents(); + scheduleTimer(); + }) + .catch((err) => { + fetchFailedCallback(self, err); + scheduleTimer(); + }); }; /* scheduleTimer() diff --git a/package-lock.json b/package-lock.json index 428fd1fe75..bfbf1daf51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3235,6 +3235,24 @@ "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==", "dev": true }, + "ical": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/ical/-/ical-0.8.0.tgz", + "integrity": "sha512-/viUSb/RGLLnlgm0lWRlPBtVeQguQRErSPYl3ugnUaKUnzQswKqOG3M8/P1v1AB5NJwlHTuvTq1cs4mpeG2rCg==", + "requires": { + "rrule": "2.4.1" + }, + "dependencies": { + "rrule": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.4.1.tgz", + "integrity": "sha512-+NcvhETefswZq13T8nkuEnnQ6YgUeZaqMqVbp+ZiFDPCbp3AVgQIwUvNVDdMNrP05bKZG9ddDULFp0qZZYDrxg==", + "requires": { + "luxon": "^1.3.3" + } + } + } + }, "iconv-lite": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz", @@ -4714,8 +4732,7 @@ "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "dev": true + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, "node-releases": { "version": "1.1.53", diff --git a/package.json b/package.json index f568d73c64..977a653e27 100644 --- a/package.json +++ b/package.json @@ -72,10 +72,12 @@ "express-ipfilter": "^1.0.1", "feedme": "latest", "helmet": "^3.21.2", + "ical": "^0.8.0", "iconv-lite": "latest", "lodash": "^4.17.15", "module-alias": "^2.2.2", "moment": "latest", + "node-fetch": "^2.6.0", "request": "^2.88.0", "rrule": "^2.6.2", "rrule-alt": "^2.2.8", From 7ab74c6cc94e713e5723f2b927b2e84132ce14a4 Mon Sep 17 00:00:00 2001 From: rejas Date: Wed, 17 Jun 2020 21:17:35 +0200 Subject: [PATCH 02/11] Remove old ical version --- .../calendar/vendor/ical.js/.travis.yml | 4 - .../default/calendar/vendor/ical.js/LICENSE | 178 --- .../default/calendar/vendor/ical.js/NOTICE | 13 - .../calendar/vendor/ical.js/example.js | 16 - .../calendar/vendor/ical.js/example_rrule.js | 118 -- .../vendor/ical.js/examples/example_rrule.ics | 40 - .../default/calendar/vendor/ical.js/ical.js | 452 ------- .../default/calendar/vendor/ical.js/index.js | 8 - .../calendar/vendor/ical.js/node-ical.js | 77 -- .../calendar/vendor/ical.js/package.json | 29 - .../default/calendar/vendor/ical.js/readme.md | 62 - .../calendar/vendor/ical.js/test/test.js | 500 ------- .../calendar/vendor/ical.js/test/test1.ics | 78 -- .../calendar/vendor/ical.js/test/test10.ics | 34 - .../calendar/vendor/ical.js/test/test11.ics | 41 - .../calendar/vendor/ical.js/test/test12.ics | 19 - .../calendar/vendor/ical.js/test/test13.ics | 57 - .../calendar/vendor/ical.js/test/test14.ics | 33 - .../calendar/vendor/ical.js/test/test2.ics | 83 -- .../calendar/vendor/ical.js/test/test3.ics | 226 ---- .../calendar/vendor/ical.js/test/test4.ics | 747 ----------- .../calendar/vendor/ical.js/test/test5.ics | 41 - .../calendar/vendor/ical.js/test/test6.ics | 1170 ----------------- .../calendar/vendor/ical.js/test/test7.ics | 16 - .../calendar/vendor/ical.js/test/test8.ics | 23 - .../calendar/vendor/ical.js/test/test9.ics | 21 - 26 files changed, 4086 deletions(-) delete mode 100644 modules/default/calendar/vendor/ical.js/.travis.yml delete mode 100644 modules/default/calendar/vendor/ical.js/LICENSE delete mode 100644 modules/default/calendar/vendor/ical.js/NOTICE delete mode 100644 modules/default/calendar/vendor/ical.js/example.js delete mode 100644 modules/default/calendar/vendor/ical.js/example_rrule.js delete mode 100644 modules/default/calendar/vendor/ical.js/examples/example_rrule.ics delete mode 100644 modules/default/calendar/vendor/ical.js/ical.js delete mode 100644 modules/default/calendar/vendor/ical.js/index.js delete mode 100644 modules/default/calendar/vendor/ical.js/node-ical.js delete mode 100644 modules/default/calendar/vendor/ical.js/package.json delete mode 100644 modules/default/calendar/vendor/ical.js/readme.md delete mode 100644 modules/default/calendar/vendor/ical.js/test/test.js delete mode 100644 modules/default/calendar/vendor/ical.js/test/test1.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test10.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test11.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test12.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test13.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test14.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test2.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test3.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test4.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test5.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test6.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test7.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test8.ics delete mode 100644 modules/default/calendar/vendor/ical.js/test/test9.ics diff --git a/modules/default/calendar/vendor/ical.js/.travis.yml b/modules/default/calendar/vendor/ical.js/.travis.yml deleted file mode 100644 index d5d4c1e3e2..0000000000 --- a/modules/default/calendar/vendor/ical.js/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: node_js -node_js: - - "8.9" -install: npm install diff --git a/modules/default/calendar/vendor/ical.js/LICENSE b/modules/default/calendar/vendor/ical.js/LICENSE deleted file mode 100644 index e454a52586..0000000000 --- a/modules/default/calendar/vendor/ical.js/LICENSE +++ /dev/null @@ -1,178 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/modules/default/calendar/vendor/ical.js/NOTICE b/modules/default/calendar/vendor/ical.js/NOTICE deleted file mode 100644 index d5f926dbc8..0000000000 --- a/modules/default/calendar/vendor/ical.js/NOTICE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2012 Peter Braden - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/modules/default/calendar/vendor/ical.js/example.js b/modules/default/calendar/vendor/ical.js/example.js deleted file mode 100644 index 7b41f1ad39..0000000000 --- a/modules/default/calendar/vendor/ical.js/example.js +++ /dev/null @@ -1,16 +0,0 @@ -'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 (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 deleted file mode 100644 index 6233c4b289..0000000000 --- a/modules/default/calendar/vendor/ical.js/example_rrule.js +++ /dev/null @@ -1,118 +0,0 @@ -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 deleted file mode 100644 index 4f72c0ecb4..0000000000 --- a/modules/default/calendar/vendor/ical.js/examples/example_rrule.ics +++ /dev/null @@ -1,40 +0,0 @@ -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/ical.js b/modules/default/calendar/vendor/ical.js/ical.js deleted file mode 100644 index 024625b750..0000000000 --- a/modules/default/calendar/vendor/ical.js/ical.js +++ /dev/null @@ -1,452 +0,0 @@ -(function(name, definition) { - -/**************** - * A tolerant, minimal icalendar parser - * (http://tools.ietf.org/html/rfc5545) - * - * - * **************/ - - if (typeof module !== 'undefined') { - module.exports = definition(); - } else if (typeof define === 'function' && typeof define.amd === 'object'){ - define(definition); - } else { - this[name] = definition(); - } - -}('ical', function(){ - - // Unescape Text re RFC 4.3.11 - var text = function(t){ - t = t || ""; - return (t - .replace(/\\\,/g, ',') - .replace(/\\\;/g, ';') - .replace(/\\[nN]/g, '\n') - .replace(/\\\\/g, '\\') - ) - } - - var parseParams = function(p){ - var out = {} - for (var i = 0; i 0) { - //trimming the leading and perform storeParam - name = name.substring(2); - return (storeParam(name))(val, params, ctx, stack, line); - } - - return storeParam(name.toLowerCase())(val, params, ctx); - }, - - - parseICS : function(str){ - var self = this - var lines = str.split(/\r?\n/) - var ctx = {} - var stack = [] - - for (var i = 0, ii = lines.length, l = lines[0]; i (peterbraden.co.uk)", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "git://github.com/peterbraden/ical.js.git" - }, - "dependencies": { - "request": "^2.88.0", - "rrule": "2.4.1" - }, - "devDependencies": { - "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 deleted file mode 100644 index 5f05643605..0000000000 --- a/modules/default/calendar/vendor/ical.js/readme.md +++ /dev/null @@ -1,62 +0,0 @@ -# ical.js # -(Formerly node-ical) - -[![Build Status](https://travis-ci.org/peterbraden/ical.js.png)](https://travis-ci.org/peterbraden/ical.js) - -A tolerant, minimal icalendar parser for javascript/node -(http://tools.ietf.org/html/rfc5545) - - - -## Install - Node.js ## - -ical.js is availble on npm: - - npm install ical - - - -## API ## - - ical.parseICS(str) - -Parses a string with an ICS File - - var data = ical.parseFile(filename) - -Reads in the specified iCal file, parses it and returns the parsed data - - ical.fromURL(url, options, function(err, data) {} ) - -Use the request library to fetch the specified URL (```opts``` gets passed on to the ```request()``` call), and call the function with the result (either an error or the data). - - - -## Example 1 - Print list of upcoming node conferences (see example.js) -```javascript -'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 (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 deleted file mode 100644 index c20587a409..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test.js +++ /dev/null @@ -1,500 +0,0 @@ -/**** - * Tests - * - * - ***/ -process.env.TZ = 'America/San_Francisco'; -var ical = require('../index') - -var vows = require('vows') - , assert = require('assert') - , _ = require('underscore') - -vows.describe('node-ical').addBatch({ - 'when parsing test1.ics (node conferences schedule from lanyrd.com, modified)': { - topic: function () { - return ical.parseFile('./test/test1.ics') - } - - ,'we get 9 events': function (topic) { - var events = _.select(_.values(topic), function(x){ return x.type==='VEVENT'}) - assert.equal (events.length, 9); - } - - ,'event 47f6e' : { - topic: function(events){ - return _.select(_.values(events), - function(x){ - return x.uid ==='47f6ea3f28af2986a2192fa39a91fa7d60d26b76'})[0] - } - ,'is in fort lauderdale' : function(topic){ - assert.equal(topic.location, "Fort Lauderdale, United States") - } - ,'starts Tue, 29 Nov 2011' : function(topic){ - assert.equal(topic.start.toDateString(), new Date(2011,10,29).toDateString()) - } - } - , 'event 480a' : { - topic: function(events){ - return _.select(_.values(events), - function(x){ - return x.uid ==='480a3ad48af5ed8965241f14920f90524f533c18'})[0] - } - , '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){ - return _.select(_.values(events), - function(x){ - return x.uid === 'd4c826dfb701f611416d69b4df81caf9ff80b03a'})[0] - } - , 'has a start datetime' : function(topic){ - assert.equal(topic.start.toDateString(), new Date(Date.UTC(2011, 2, 12, 20, 0, 0)).toDateString()) - } - } - - , 'event sdfkf09fsd0 (Invalid Date)' :{ - topic : function(events){ - return _.select(_.values(events), - function(x){ - return x.uid === 'sdfkf09fsd0'})[0] - } - , 'has a start datetime' : function(topic){ - assert.equal(topic.start, "Next Year") - } - } - } - , 'with test2.ics (testing ical features)' : { - topic: function () { - return ical.parseFile('./test/test2.ics') - } - , 'todo item uid4@host1.com' : { - topic : function(items){ - return items['uid4@host1.com'] - } - , 'is a VTODO' : function(topic){ - assert.equal(topic.type, 'VTODO') - } - } - , 'vfreebusy' : { - topic: function(events) { - return _.select(_.values(events), function(x) { - return x.type === 'VFREEBUSY'; - })[0]; - } - , 'has a URL' : function(topic) { - assert.equal(topic.url, 'http://www.host.com/calendar/busytime/jsmith.ifb'); - } - } - , 'vfreebusy first freebusy' : { - topic: function(events) { - return _.select(_.values(events), function(x) { - return x.type === 'VFREEBUSY'; - })[0].freebusy[0]; - } - , 'has undefined type defaulting to busy' : function(topic) { - assert.equal(topic.type, "BUSY"); - } - , 'has an start datetime' : function(topic) { - assert.equal(topic.start.getFullYear(), 1998); - assert.equal(topic.start.getUTCMonth(), 2); - assert.equal(topic.start.getUTCDate(), 14); - assert.equal(topic.start.getUTCHours(), 23); - assert.equal(topic.start.getUTCMinutes(), 30); - } - , 'has an end datetime' : function(topic) { - assert.equal(topic.end.getFullYear(), 1998); - assert.equal(topic.end.getUTCMonth(), 2); - assert.equal(topic.end.getUTCDate(), 15); - assert.equal(topic.end.getUTCHours(), 00); - assert.equal(topic.end.getUTCMinutes(), 30); - } - } - } - , 'with test3.ics (testing tvcountdown.com)' : { - topic: function() { - return ical.parseFile('./test/test3.ics'); - } - , 'event -83' : { - topic: function(events) { - return _.select(_.values(events), function(x) { - return x.uid === '20110505T220000Z-83@tvcountdown.com'; - })[0]; - } - , 'has a start datetime' : function(topic) { - assert.equal(topic.start.getFullYear(), 2011); - assert.equal(topic.start.getMonth(), 4); - } - , 'has an end datetime' : function(topic) { - assert.equal(topic.end.getFullYear(), 2011); - assert.equal(topic.end.getMonth(), 4); - } - } - } - - , 'with test4.ics (testing tripit.com)' : { - topic: function() { - return ical.parseFile('./test/test4.ics'); - } - , 'event c32a5...' : { - topic: function(events) { - return _.select(_.values(events), function(x) { - return x.uid === 'c32a5eaba2354bb29e012ec18da827db90550a3b@tripit.com'; - })[0]; - } - , 'has a start datetime' : function(topic) { - assert.equal(topic.start.getFullYear(), 2011); - assert.equal(topic.start.getMonth(), 09); - assert.equal(topic.start.getDate(), 11); - } - - , 'has a summary' : function(topic){ - // escaped commas and semicolons should be replaced - assert.equal(topic.summary, 'South San Francisco, CA, October 2011;') - - } - - , 'has a description' : function(topic){ - var desired = 'John Doe is in South San Francisco, CA from Oct 11 ' + - 'to Oct 13, 2011\nView and/or edit details in TripIt : http://www.tripit.c' + - 'om/trip/show/id/23710889\nTripIt - organize your travel at http://www.trip' + - 'it.com\n' - assert.equal(topic.description, desired) - - } - - , 'has a geolocation' : function(topic){ - assert.ok(topic.geo, 'no geo param') - assert.equal(topic.geo.lat, 37.654656) - assert.equal(topic.geo.lon, -122.40775) - } - - , 'has transparency' : function(topic){ - assert.equal(topic.transparency, 'TRANSPARENT') - } - - } - } - - - - , 'with test5.ics (testing meetup.com)' : { - topic: function () { - return ical.parseFile('./test/test5.ics') - } - , 'event nsmxnyppbfc@meetup.com' : { - topic: function(events) { - return _.select(_.values(events), function(x) { - return x.uid === 'event_nsmxnyppbfc@meetup.com'; - })[0]; - } - , 'has a start' : function(topic){ - assert.equal(topic.start.tz, 'America/Phoenix') - assert.equal(topic.start.toISOString(), new Date(2011, 10, 09, 19, 0,0).toISOString()) - } - } - } - - , 'with test6.ics (testing assembly.org)': { - topic: function () { - return ical.parseFile('./test/test6.ics') - } - , 'event with no ID' : { - topic: function(events) { - return _.select(_.values(events), function(x) { - return x.summary === 'foobar Summer 2011 starts!'; - })[0]; - } - , 'has a start' : function(topic){ - assert.equal(topic.start.toISOString(), new Date(2011, 07, 04, 12, 0,0).toISOString()) - } - } - , 'event with rrule' :{ - topic: function(events){ - return _.select(_.values(events), function(x){ - return x.summary === "foobarTV broadcast starts" - })[0]; - } - , "Has an RRULE": function(topic){ - assert.notEqual(topic.rrule, undefined); - } - , "RRule text": function(topic){ - assert.equal(topic.rrule.toText(), "every 5 weeks on Monday, Friday until January 30, 2013") - } - } - } - , 'with test7.ics (testing dtstart of rrule)' :{ - topic: function() { - return ical.parseFile('./test/test7.ics'); - }, - 'recurring yearly event (14 july)': { - topic: function(events){ - var ev = _.values(events)[0]; - return ev.rrule.between(new Date(2013, 0, 1), new Date(2014, 0, 1)); - }, - 'dt start well set': function(topic) { - assert.equal(topic[0].toDateString(), new Date(2013, 6, 14).toDateString()); - } - } - } - , "with test 8.ics (VTODO completion)": { - topic: function() { - return ical.parseFile('./test/test8.ics'); - }, - 'grabbing VTODO task': { - topic: function(topic) { - return _.values(topic)[0]; - }, - 'task completed': function(task){ - assert.equal(task.completion, 100); - assert.equal(task.completed.toISOString(), new Date(2013, 06, 16, 10, 57, 45).toISOString()); - } - } - } - , "with test 9.ics (VEVENT with VALARM)": { - topic: function() { - return ical.parseFile('./test/test9.ics'); - }, - 'grabbing VEVENT task': { - topic: function(topic) { - return _.values(topic)[0]; - }, - 'task completed': function(task){ - assert.equal(task.summary, "Event with an alarm"); - } - } - } - , 'with test 11.ics (VEVENT with custom properties)': { - topic: function() { - return ical.parseFile('./test10.ics'); - }, - 'grabbing custom properties': { - topic: function(topic) { - - } - } - }, - - 'with test10.ics': { - topic: function () { - return ical.parseFile('./test/test10.ics'); - }, - - 'when categories present': { - topic: function (t) {return _.values(t)[0]}, - - 'should be a list': function (e) { - assert(e.categories instanceof [].constructor); - }, - - 'should contain individual category values': function (e) { - assert.deepEqual(e.categories, ['cat1', 'cat2', 'cat3']); - } - }, - - 'when categories present with trailing whitespace': { - topic: function (t) {return _.values(t)[1]}, - - 'should contain individual category values without whitespace': function (e) { - assert.deepEqual(e.categories, ['cat1', 'cat2', 'cat3']); - } - }, - - 'when categories present but empty': { - topic: function (t) {return _.values(t)[2]}, - - 'should be an empty list': function (e) { - assert.deepEqual(e.categories, []); - } - }, - - 'when categories present but singular': { - topic: function (t) {return _.values(t)[3]}, - - 'should be a list of single item': function (e) { - assert.deepEqual(e.categories, ['lonely-cat']); - } - }, - - 'when categories present on multiple lines': { - topic: function (t) {return _.values(t)[4]}, - - 'should contain the category values in an array': function (e) { - assert.deepEqual(e.categories, ['cat1', 'cat2', 'cat3']); - } - } - }, - - 'with test11.ics (testing zimbra freebusy)': { - topic: function () { - return ical.parseFile('./test/test11.ics'); - }, - - 'freebusy params' : { - topic: function(events) { - return _.values(events)[0]; - } - , 'has a URL' : function(topic) { - assert.equal(topic.url, 'http://mail.example.com/yvr-2a@example.com/20140416'); - } - , 'has an ORGANIZER' : function(topic) { - assert.equal(topic.organizer, 'mailto:yvr-2a@example.com'); - } - , 'has an start datetime' : function(topic) { - assert.equal(topic.start.getFullYear(), 2014); - assert.equal(topic.start.getMonth(), 3); - } - , 'has an end datetime' : function(topic) { - assert.equal(topic.end.getFullYear(), 2014); - assert.equal(topic.end.getMonth(), 6); - } - } - , 'freebusy busy events' : { - topic: function(events) { - return _.select(_.values(events)[0].freebusy, function(x) { - return x.type === 'BUSY'; - })[0]; - } - , 'has an start datetime' : function(topic) { - assert.equal(topic.start.getFullYear(), 2014); - assert.equal(topic.start.getMonth(), 3); - assert.equal(topic.start.getUTCHours(), 15); - assert.equal(topic.start.getUTCMinutes(), 15); - } - , 'has an end datetime' : function(topic) { - assert.equal(topic.end.getFullYear(), 2014); - assert.equal(topic.end.getMonth(), 3); - assert.equal(topic.end.getUTCHours(), 19); - assert.equal(topic.end.getUTCMinutes(), 00); - } - } - } - - , '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://255.255.255.255/', {}, this.callback); - } - , 'are passed back to the callback' : function (err, result) { - assert.instanceOf(err, Error); - if (!err){ - console.log(">E:", err, result) - } - } - } -}).export(module) - - -//ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', -// {}, -// function(err, data){ -// console.log("OUT:", data) -// }) diff --git a/modules/default/calendar/vendor/ical.js/test/test1.ics b/modules/default/calendar/vendor/ical.js/test/test1.ics deleted file mode 100644 index ff8cc076af..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test1.ics +++ /dev/null @@ -1,78 +0,0 @@ -BEGIN:VCALENDAR -PRODID:-//lanyrd.com//Lanyrd//EN -X-ORIGINAL-URL:http://lanyrd.com/topics/nodejs/nodejs.ics -X-WR-CALNAME;CHARSET=utf-8:Node.js conferences -VERSION:2.0 -METHOD:PUBLISH -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:Dyncon 2011 -LOCATION;CHARSET=utf-8:Stockholm, Sweden -URL:http://lanyrd.com/2011/dyncon/ -UID:d4c826dfb701f611416d69b4df81caf9ff80b03a -DTSTART:20110312T200000Z -DTEND;VALUE=DATE:20110314 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:[Async]: Everything Express -LOCATION;CHARSET=utf-8:Brighton, United Kingdom -URL:http://lanyrd.com/2011/asyncjs-express/ -UID:480a3ad48af5ed8965241f14920f90524f533c18 -DTSTART;VALUE=DATE:20110324 -DTEND;VALUE=DATE:20110325 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:JSConf US 2011 -LOCATION;CHARSET=utf-8:Portland, United States -URL:http://lanyrd.com/2011/jsconf/ -UID:ed334cc85db5ebdff5ff5a630a7a48631a677dbe -DTSTART;VALUE=DATE:20110502 -DTEND;VALUE=DATE:20110504 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:NodeConf 2011 -LOCATION;CHARSET=utf-8:Portland, United States -URL:http://lanyrd.com/2011/nodeconf/ -UID:25169a7b1ba5c248278f47120a40878055dc8c15 -DTSTART;VALUE=DATE:20110505 -DTEND;VALUE=DATE:20110506 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:BrazilJS -LOCATION;CHARSET=utf-8:Fortaleza, Brazil -URL:http://lanyrd.com/2011/braziljs/ -UID:dafee3be83624f3388c5635662229ff11766bb9c -DTSTART;VALUE=DATE:20110513 -DTEND;VALUE=DATE:20110515 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:Falsy Values -LOCATION;CHARSET=utf-8:Warsaw, Poland -URL:http://lanyrd.com/2011/falsy-values/ -UID:73cad6a09ac4e7310979c6130f871d17d990b5ad -DTSTART;VALUE=DATE:20110518 -DTEND;VALUE=DATE:20110521 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:nodecamp.eu -LOCATION;CHARSET=utf-8:Cologne, Germany -URL:http://lanyrd.com/2011/nodecampde/ -UID:b728a5fdb5f292b6293e4a2fd97a1ccfc69e9d6f -DTSTART;VALUE=DATE:20110611 -DTEND;VALUE=DATE:20110613 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:Rich Web Experience 2011 -LOCATION;CHARSET=utf-8:Fort Lauderdale, United States -URL:http://lanyrd.com/2011/rich-web-experience/ -UID:47f6ea3f28af2986a2192fa39a91fa7d60d26b76 -DTSTART;VALUE=DATE:20111129 -DTEND;VALUE=DATE:20111203 -END:VEVENT -BEGIN:VEVENT -SUMMARY;CHARSET=utf-8:Foobar -UID:sdfkf09fsd0 -DTSTART;VALUE=DATE:Next Year -DTEND;VALUE=DATE:20111203 -END:VEVENT - -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test10.ics b/modules/default/calendar/vendor/ical.js/test/test10.ics deleted file mode 100644 index 40763b3b4c..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test10.ics +++ /dev/null @@ -1,34 +0,0 @@ -BEGIN:VCALENDAR -BEGIN:VEVENT -UID:1 -SUMMARY:Event with a category -DESCRIPTION:Details for an event with a category -CATEGORIES:cat1,cat2,cat3 -END:VEVENT -BEGIN:VEVENT -UID:2 -SUMMARY:Event with a category -DESCRIPTION:Details for an event with a category -CATEGORIES:cat1 , cat2, cat3 -END:VEVENT -BEGIN:VEVENT -UID:3 -SUMMARY:Event with a category -DESCRIPTION:Details for an event with a category -CATEGORIES: -END:VEVENT -BEGIN:VEVENT -UID:4 -SUMMARY:Event with a category -DESCRIPTION:Details for an event with a category -CATEGORIES:lonely-cat -END:VEVENT -BEGIN:VEVENT -UID:5 -SUMMARY:Event with a category -DESCRIPTION:Details for an event with a category -CATEGORIES:cat1 -CATEGORIES:cat2 -CATEGORIES:cat3 -END:VEVENT -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test11.ics b/modules/default/calendar/vendor/ical.js/test/test11.ics deleted file mode 100644 index 3a7e80de9a..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test11.ics +++ /dev/null @@ -1,41 +0,0 @@ -BEGIN:VCALENDAR -PRODID:Zimbra-Calendar-Provider -VERSION:2.0 -METHOD:PUBLISH -BEGIN:VFREEBUSY -ORGANIZER:mailto:yvr-2a@example.com -DTSTAMP:20140516T235436Z -DTSTART:20140415T235436Z -DTEND:20140717T235436Z -URL:http://mail.example.com/yvr-2a@example.com/20140416 -FREEBUSY;FBTYPE=BUSY:20140416T151500Z/20140416T190000Z -FREEBUSY;FBTYPE=BUSY:20140416T195500Z/20140416T231500Z -FREEBUSY;FBTYPE=BUSY:20140417T193000Z/20140417T203000Z -FREEBUSY;FBTYPE=BUSY:20140421T210000Z/20140421T213000Z -FREEBUSY;FBTYPE=BUSY:20140423T180000Z/20140423T190000Z -FREEBUSY;FBTYPE=BUSY:20140423T200000Z/20140423T210000Z -FREEBUSY;FBTYPE=BUSY:20140423T223500Z/20140423T231500Z -FREEBUSY;FBTYPE=BUSY:20140424T155000Z/20140424T165500Z -FREEBUSY;FBTYPE=BUSY:20140424T170000Z/20140424T183000Z -FREEBUSY;FBTYPE=BUSY:20140424T195000Z/20140424T230000Z -FREEBUSY;FBTYPE=BUSY:20140425T144500Z/20140425T161500Z -FREEBUSY;FBTYPE=BUSY:20140425T180000Z/20140425T194500Z -FREEBUSY;FBTYPE=BUSY:20140425T223000Z/20140425T230000Z -FREEBUSY;FBTYPE=BUSY:20140428T151500Z/20140428T163000Z -FREEBUSY;FBTYPE=BUSY:20140428T170000Z/20140428T173000Z -FREEBUSY;FBTYPE=BUSY:20140428T195500Z/20140428T213000Z -FREEBUSY;FBTYPE=BUSY:20140428T231000Z/20140428T234000Z -FREEBUSY;FBTYPE=BUSY:20140429T152500Z/20140429T170000Z -FREEBUSY;FBTYPE=BUSY:20140429T180000Z/20140429T183000Z -FREEBUSY;FBTYPE=BUSY:20140429T201500Z/20140429T230000Z -FREEBUSY;FBTYPE=BUSY:20140430T162500Z/20140430T165500Z -FREEBUSY;FBTYPE=BUSY:20140430T180000Z/20140430T190000Z -FREEBUSY;FBTYPE=BUSY:20140501T170000Z/20140501T173000Z -FREEBUSY;FBTYPE=BUSY:20140501T175000Z/20140501T190000Z -FREEBUSY;FBTYPE=BUSY:20140501T232000Z/20140501T235000Z -FREEBUSY;FBTYPE=BUSY:20140502T163500Z/20140502T173000Z -FREEBUSY;FBTYPE=BUSY:20140505T165500Z/20140505T173000Z -FREEBUSY;FBTYPE=BUSY:20140505T201500Z/20140505T203000Z -FREEBUSY;FBTYPE=BUSY:20140505T210000Z/20140505T213000Z -END:VFREEBUSY -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test12.ics b/modules/default/calendar/vendor/ical.js/test/test12.ics deleted file mode 100644 index 4e78603b03..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test12.ics +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index 3118186bed..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test13.ics +++ /dev/null @@ -1,57 +0,0 @@ -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 deleted file mode 100644 index 5c4f5cafb8..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test14.ics +++ /dev/null @@ -1,33 +0,0 @@ -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 diff --git a/modules/default/calendar/vendor/ical.js/test/test2.ics b/modules/default/calendar/vendor/ical.js/test/test2.ics deleted file mode 100644 index 29baf8cd92..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test2.ics +++ /dev/null @@ -1,83 +0,0 @@ -BEGIN:VCALENDAR -CALSCALE:GREGORIAN -X-WR-TIMEZONE;VALUE=TEXT:US/Pacific -METHOD:PUBLISH -PRODID:-//Apple Computer\, Inc//iCal 1.0//EN -X-WR-CALNAME;VALUE=TEXT:Example -VERSION:2.0 -BEGIN:VEVENT -SEQUENCE:5 -DTSTART;TZID=US/Pacific:20021028T140000 -DTSTAMP:20021028T011706Z -SUMMARY:Coffee with Jason -UID:EC9439B1-FF65-11D6-9973-003065F99D04 -DTEND;TZID=US/Pacific:20021028T150000 -END:VEVENT -BEGIN:VALARM -TRIGGER;VALUE=DURATION:-P1D -ACTION:DISPLAY -DESCRIPTION:Event reminder -END:VALARM -BEGIN:VEVENT -SEQUENCE:1 -DTSTAMP:20021128T012034Z -SUMMARY:Code Review -UID:EC944331-FF65-11D6-9973-003065F99D04 -DTSTART;TZID=US/Pacific:20021127T120000 -DURATION:PT1H -END:VEVENT -BEGIN:VEVENT -SEQUENCE:1 -DTSTAMP:20021028T012034Z -SUMMARY:Dinner with T -UID:EC944CFA-FF65-11D6-9973-003065F99D04 -DTSTART;TZID=US/Pacific:20021216T200000 -DURATION:PT1H -END:VEVENT -BEGIN:VTODO -DTSTAMP:19980130T134500Z -SEQUENCE:2 -UID:uid4@host1.com -ORGANIZER:MAILTO:unclesam@us.gov -ATTENDEE;PARTSTAT=ACCEPTED:MAILTO:jqpublic@host.com -DUE:19980415T235959 -STATUS:NEEDS-ACTION -SUMMARY:Submit Income Taxes -END:VTODO -BEGIN:VALARM -ACTION:AUDIO -TRIGGER:19980403T120000 -ATTACH;FMTTYPE=audio/basic:http://host.com/pub/audio- - files/ssbanner.aud -REPEAT:4 -DURATION:PT1H -END:VALARM -BEGIN:VJOURNAL -DTSTAMP:19970324T120000Z -UID:uid5@host1.com -ORGANIZER:MAILTO:jsmith@host.com -STATUS:DRAFT -CLASS:PUBLIC -CATEGORY:Project Report, XYZ, Weekly Meeting -DESCRIPTION:Project xyz Review Meeting Minutes\n - Agenda\n1. Review of project version 1.0 requirements.\n2. - Definition - of project processes.\n3. Review of project schedule.\n - Participants: John Smith, Jane Doe, Jim Dandy\n-It was - decided that the requirements need to be signed off by - product marketing.\n-Project processes were accepted.\n - -Project schedule needs to account for scheduled holidays - and employee vacation time. Check with HR for specific - dates.\n-New schedule will be distributed by Friday.\n- - Next weeks meeting is cancelled. No meeting until 3/23. -END:VJOURNAL -BEGIN:VFREEBUSY -ORGANIZER:MAILTO:jsmith@host.com -DTSTART:19980313T141711Z -DTEND:19980410T141711Z -FREEBUSY:19980314T233000Z/19980315T003000Z -FREEBUSY:19980316T153000Z/19980316T163000Z -FREEBUSY:19980318T030000Z/19980318T040000Z -URL:http://www.host.com/calendar/busytime/jsmith.ifb -END:VFREEBUSY -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test3.ics b/modules/default/calendar/vendor/ical.js/test/test3.ics deleted file mode 100644 index ee7111e7a4..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test3.ics +++ /dev/null @@ -1,226 +0,0 @@ -BEGIN:VCALENDAR -CALSCALE:GREGORIAN -PRODID:tvcountdown.com -X-WR-CALNAME:tvcountdown.com -VERSION:2.0 -METHOD:PUBLISH -X-WR-TIMEZONE:US/Eastern -X-WR-CALNAME;VALUE=TEXT:tvcountdown.com -X-WR-CALDESC: -BEGIN:VEVENT -UID:20110519T200000Z-79@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110519T200000 -DTEND;VALUE=DATE-TIME:20110519T203000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Big Bang Theory - S04E24 - The Roomate Transmogrfication -END:VEVENT -BEGIN:VEVENT -UID:20110512T200000Z-79@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110512T200000 -DTEND;VALUE=DATE-TIME:20110512T203000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Big Bang Theory - S04E23 - The Engagement Reaction -END:VEVENT -BEGIN:VEVENT -UID:20110505T220000Z-83@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110505T220000 -DTEND;VALUE=DATE-TIME:20110505T223000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:30 Rock - S05E23 - Respawn -END:VEVENT -BEGIN:VEVENT -UID:20110505T200000Z-79@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110505T200000 -DTEND;VALUE=DATE-TIME:20110505T203000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Big Bang Theory - S04E22 - The Wildebeest Implementation -END:VEVENT -BEGIN:VEVENT -UID:20110504T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110504T230000 -DTEND;VALUE=DATE-TIME:20110504T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E59 - David Barton -END:VEVENT -BEGIN:VEVENT -UID:20110503T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110503T230000 -DTEND;VALUE=DATE-TIME:20110503T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E58 - Rachel Maddow -END:VEVENT -BEGIN:VEVENT -UID:20110502T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110502T230000 -DTEND;VALUE=DATE-TIME:20110502T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E57 - Philip K. Howard -END:VEVENT -BEGIN:VEVENT -UID:20110428T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110428T230000 -DTEND;VALUE=DATE-TIME:20110428T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E56 - William Cohan -END:VEVENT -BEGIN:VEVENT -UID:20110428T220000Z-83@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110428T220000 -DTEND;VALUE=DATE-TIME:20110428T223000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:30 Rock - S05E22 - Everything Sunny All the Time Always -END:VEVENT -BEGIN:VEVENT -UID:20110428T200000Z-79@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110428T200000 -DTEND;VALUE=DATE-TIME:20110428T203000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Big Bang Theory - S04E21 - The Agreement Dissection -END:VEVENT -BEGIN:VEVENT -UID:20110427T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110427T230000 -DTEND;VALUE=DATE-TIME:20110427T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E55 - Sen. Bernie Sanders -END:VEVENT -BEGIN:VEVENT -UID:20110426T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110426T230000 -DTEND;VALUE=DATE-TIME:20110426T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E54 - Elizabeth Warren -END:VEVENT -BEGIN:VEVENT -UID:20110425T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110425T230000 -DTEND;VALUE=DATE-TIME:20110425T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E53 - Gigi Ibrahim -END:VEVENT -BEGIN:VEVENT -UID:20110421T220000Z-83@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110421T220000 -DTEND;VALUE=DATE-TIME:20110421T223000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:30 Rock - S05E21 - 100th Episode Part 2 of 2 -END:VEVENT -BEGIN:VEVENT -UID:20110421T220000Z-83@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110421T220000 -DTEND;VALUE=DATE-TIME:20110421T223000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:30 Rock - S05E20 - 100th Episode Part 1 of 2 -END:VEVENT -BEGIN:VEVENT -UID:20110414T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110414T230000 -DTEND;VALUE=DATE-TIME:20110414T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E52 - Ricky Gervais -END:VEVENT -BEGIN:VEVENT -UID:20110414T220000Z-83@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110414T220000 -DTEND;VALUE=DATE-TIME:20110414T223000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:30 Rock - S05E19 - I Heart Connecticut -END:VEVENT -BEGIN:VEVENT -UID:20110413T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110413T230000 -DTEND;VALUE=DATE-TIME:20110413T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E51 - Tracy Morgan -END:VEVENT -BEGIN:VEVENT -UID:20110412T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110412T230000 -DTEND;VALUE=DATE-TIME:20110412T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E50 - Gov. Deval Patrick -END:VEVENT -BEGIN:VEVENT -UID:20110411T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110411T230000 -DTEND;VALUE=DATE-TIME:20110411T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E49 - Foo Fighters -END:VEVENT -BEGIN:VEVENT -UID:20110407T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110407T230000 -DTEND;VALUE=DATE-TIME:20110407T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E48 - Jamie Oliver -END:VEVENT -BEGIN:VEVENT -UID:20110407T200000Z-79@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110407T200000 -DTEND;VALUE=DATE-TIME:20110407T203000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Big Bang Theory - S04E20 - The Herb Garden Germination -END:VEVENT -BEGIN:VEVENT -UID:20110406T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110406T230000 -DTEND;VALUE=DATE-TIME:20110406T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E47 - Mike Huckabee -END:VEVENT -BEGIN:VEVENT -UID:20110405T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110405T230000 -DTEND;VALUE=DATE-TIME:20110405T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E46 - Colin Quinn -END:VEVENT -BEGIN:VEVENT -UID:20110404T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110404T230000 -DTEND;VALUE=DATE-TIME:20110404T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E45 - Billy Crystal -END:VEVENT -BEGIN:VEVENT -UID:20110331T230000Z-289@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110331T230000 -DTEND;VALUE=DATE-TIME:20110331T233000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Daily Show - S16E44 - Norm MacDonald -END:VEVENT -BEGIN:VEVENT -UID:20110331T200000Z-79@tvcountdown.com -DTSTART;VALUE=DATE-TIME:20110331T200000 -DTEND;VALUE=DATE-TIME:20110331T203000 -DTSTAMP:20110430T192946Z -URL;VALUE=URI: -SUMMARY:The Big Bang Theory - S04E19 - The Zarnecki Incursion -END:VEVENT -END:VCALENDAR \ No newline at end of file diff --git a/modules/default/calendar/vendor/ical.js/test/test4.ics b/modules/default/calendar/vendor/ical.js/test/test4.ics deleted file mode 100644 index 390a404c15..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test4.ics +++ /dev/null @@ -1,747 +0,0 @@ -BEGIN:VCALENDAR -X-WR-CALNAME:John Doe (TripIt) -X-WR-CALDESC:TripIt Calendar -X-PUBLISHED-TTL:PT15M -PRODID:-//John Doe/NONSGML Bennu 0.1//EN -VERSION:2.0 -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -UID:c32a5eaba2354bb29e012ec18da827db90550a3b@tripit.com -DTSTART;VALUE=DATE:20111011 -DTEND;VALUE=DATE:20111014 -SUMMARY:South San Francisco\, CA\, October 2011\; -LOCATION:South San Francisco\, CA -GEO:37.654656;-122.40775 -TRANSP:TRANSPARENT -DESCRIPTION:John Doe is in South San Francisco\, CA from Oct 11 - to Oct 13\, 2011\nView and/or edit details in TripIt : http://www.tripit.c - om/trip/show/id/23710889\nTripIt - organize your travel at http://www.trip - it.com\n -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -TRANSP:TRANSPARENT -UID:item-ee275ccffa83f492d9eb63b01953b39f18d4f944@tripit.com -DTSTART:20111011T100500 -DTEND:20111011T110500 -SUMMARY:Directions from SFO to Embassy Suites San Francisco Airport - Sout - h San Francisco -LOCATION:250 GATEWAY BLVD\, South San Francisco\, CA\, 94080 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/1234\n \n[Directions] 10/11/2011 10:05am - Directions from S - FO to Embassy Suites San Francisco Airport - South San Francisco \nfrom: S - FO \nto: 250 GATEWAY BLVD\, South San Francisco\, CA\, 94080 \nView direct - ions here: http://maps.google.com/maps?output=mobile&saddr=SFO&daddr=250+G - ATEWAY+BLVD%2C+South+San+Francisco%2C+CA%2C+94080 \n \n \n\nTripIt - organ - ize your travel at http://www.tripit.com -GEO:37.655634;-122.401273 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111011T165500Z -SUMMARY:US403 PHX to SFO -LOCATION:Phoenix (PHX) -UID:item-c576afd397cf1f90578b4ba35e781b61ba8897db@tripit.com -DTSTART:20111011T144500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/1234\n \n[Flight] 10/11/2011 US Airways(US) #403 dep PHX 7:4 - 5am MST arr SFO 9:55am PDT\; John Doe\; seat(s) 8B\; conf #DXH9K - Z\, BXQ9WH \nBooked on http://www.americanexpress-travel.com/\; Reference - #: 4127 8626 9715\; http://www.americanexpress-travel.com/\; US:1-800-297- - 2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at htt - p://www.tripit.com -GEO:37.618889;-122.375 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Pick-up Rental Car: Dollar Rent A Car -TRANSP:TRANSPARENT -UID:item-e99a90ee1c7e4f5b68a4e551009e5bb6c475940c@tripit.com -DTSTART:20111011T172500Z -DTEND:20111011T182500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/1234\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte - rnational Airport\; primary driver John Doe\; conf #R9508361 \np - ickup 10/11/2011 10:25am\; dropoff 10/13/2011 6:49pm \nEconomy \nBooked on - http://www.americanexpress-travel.com/\; Reference #: 4127 8626 9715\; ht - tp://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582 - -2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-in: Embassy Suites San Francisco Airport - South San Francis - co -TRANSP:TRANSPARENT -UID:item-7f3288d418bed063cc82b4512e792fbb5d8ae761@tripit.com -DTSTART:20111011T185500Z -DTEND:20111011T195500Z -LOCATION:250 GATEWAY BLVD\, South San Francisco\, CA\, 94080 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/23710889\n \n[Lodging] Embassy Suites San Francisco Airport - So - uth San Francisco\; primary guest John Doe\; conf #R9508361 \n25 - 0 GATEWAY BLVD\, South San Francisco\, CA\, 94080\; tel 1.650.589.3400 \na - rrive 10/11/2011\; depart 10/13/2011\; rooms: 1 \nBooked on http://www.ame - ricanexpress-travel.com/\; Reference #: 4127 8626 9715\; http://www.americ - anexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n \n \n\ - nTripIt - organize your travel at http://www.tripit.com -GEO:37.655634;-122.401273 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-out: Embassy Suites San Francisco Airport - South San Franci - sco -TRANSP:TRANSPARENT -UID:item-5eb4cb5fc25c55b0423921e18336e57f8c34598d@tripit.com -DTSTART:20111014T011900Z -DTEND:20111014T021900Z -LOCATION:250 GATEWAY BLVD\, South San Francisco\, CA\, 94080 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/23710889\n \n[Lodging] Embassy Suites San Francisco Airport - So - uth San Francisco\; primary guest John Doe\; conf #R9508361 \n25 - 0 GATEWAY BLVD\, South San Francisco\, CA\, 94080\; tel 1.650.589.3400 \na - rrive 10/11/2011\; depart 10/13/2011\; rooms: 1 \nBooked on http://www.ame - ricanexpress-travel.com/\; Reference #: 4127 8626 9715\; http://www.americ - anexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n \n \n\ - nTripIt - organize your travel at http://www.tripit.com -GEO:37.655634;-122.401273 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Drop-off Rental Car: Dollar Rent A Car -TRANSP:TRANSPARENT -UID:item-11fdbf5d02e84646025716d9f9c7a4158e1fb025@tripit.com -DTSTART:20111014T014900Z -DTEND:20111014T024900Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/23710889\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte - rnational Airport\; primary driver John Doe\; conf #R9508361 \np - ickup 10/11/2011 10:25am\; dropoff 10/13/2011 6:49pm \nEconomy \nBooked on - http://www.americanexpress-travel.com/\; Reference #: 4127 8626 9715\; ht - tp://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582 - -2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111014T051900Z -SUMMARY:CO6256 SFO to PHX -LOCATION:San Francisco (SFO) -UID:item-cb485a571a01972d6bdc74c2b829905d6e3786bf@tripit.com -DTSTART:20111014T031900Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/23710889\n \n[Flight] 10/13/2011 Continental Airlines(CO) #6256 - dep SFO 8:19pm PDT arr PHX 10:19pm MST\; John Doe\; conf #DXH9KZ - \, BXQ9WH(Operated by United Airlines flight 6256) \nBooked on http://www. - americanexpress-travel.com/\; Reference #: 4127 8626 9715\; http://www.ame - ricanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n \n - \n\nTripIt - organize your travel at http://www.tripit.com -GEO:33.436111;-112.009444 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -UID:c7b133db1e7be2713a4a63b75dcbad209690cab5@tripit.com -DTSTART;VALUE=DATE:20111023 -DTEND;VALUE=DATE:20111028 -SUMMARY:Santa Barbara\, CA\, October 2011 -LOCATION:Santa Barbara\, CA -GEO:34.420831;-119.69819 -TRANSP:TRANSPARENT -DESCRIPTION:John Doe is in Santa Barbara\, CA from Oct 23 to Oct - 27\, 2011\nView and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\nTripIt - organize your travel at http://www.tripit.com - \n -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111023T191200Z -SUMMARY:US2719 PHX to SBA -LOCATION:Phoenix (PHX) -UID:item-c4375369e9070fcc04df39ed18c4d93087577591@tripit.com -DTSTART:20111023T173500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Flight] 10/23/2011 US Airways(US) #2719 dep PHX 10 - :35am MST arr SBA 12:12pm PDT\; John Doe Ticket #0378717202638\; - conf #A44XS5\, PRX98G\, FYYJZ4 \nBooked on http://www.americanexpress-tra - vel.com/\; Reference #: 7128 8086 8504\; http://www.americanexpress-travel - .com/\; US:1-800-297-2977\, Outside:210-582-2716\; Total Cost: $699.99 \n - \n \n\nTripIt - organize your travel at http://www.tripit.com -GEO:34.427778;-119.839444 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -TRANSP:TRANSPARENT -UID:item-962e4f045d12149319d1837ec096bf43770abd6e@tripit.com -DTSTART:20111025T094000 -DTEND:20111025T104000 -SUMMARY:Directions from Hertz to Sofitel San Francisco Bay -LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Directions] 10/25/2011 9:40am - Directions from He - rtz to Sofitel San Francisco Bay \nfrom: 780 McDonnell Road\, San Francisc - o\, CA\, 94128 \nto: 223 Twin Dolphin Drive\, Redwood City\, CA\, 94065 \n - View directions here: http://maps.google.com/maps?output=mobile&saddr=780+ - McDonnell+Road%2C+San+Francisco%2C+CA%2C+94128&daddr=223+Twin+Dolphin+Driv - e%2C+Redwood+City%2C+CA%2C+94065 \n \n \n\nTripIt - organize your travel a - t http://www.tripit.com -GEO:37.5232475;-122.261296 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111025T162600Z -SUMMARY:UA5304 SBA to SFO -LOCATION:Santa Barbara (SBA) -UID:item-ae300a6934c3820974dba2c9c5b8fae843c67693@tripit.com -DTSTART:20111025T150900Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Flight] 10/25/2011 United Airlines(UA) #5304 dep S - BA 8:09am PDT arr SFO 9:26am PDT\; John Doe Ticket #037871720263 - 8\; seat(s) 11B\; conf #A44XS5\, PRX98G\, FYYJZ4 \nBooked on http://www.am - ericanexpress-travel.com/\; Reference #: 7128 8086 8504\; http://www.ameri - canexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716\; Total - Cost: $699.99 \n \n \n\nTripIt - organize your travel at http://www.tripit - .com -GEO:37.618889;-122.375 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Pick-up Rental Car: Hertz -TRANSP:TRANSPARENT -UID:item-2a9fd5a57a4cdda4677fc6ce23738e1954fdbe2a@tripit.com -DTSTART:20111025T163000Z -DTEND:20111025T173000Z -LOCATION:780 McDonnell Road\, San Francisco\, CA\, 94128 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Car Rental] Hertz\; San Francisco International Ai - rport\; primary driver John Doe\; conf #F2633064194 \n780 McDonn - ell Road\, San Francisco\, CA\, 94128 \npickup 10/25/2011 9:30am\; dropoff - 10/27/2011 7:00pm \nToyota Corolla or similar\; 84.57 USD \nBooked on htt - p://www.hertz.com/\; Reference #: F2633064194\; http://www.hertz.com/\; 80 - 0-654-3131\; Booking Rate: 84.57 USD\; Total Cost: 333.76 USD \n \n \n\nTr - ipIt - organize your travel at http://www.tripit.com -GEO:37.6297569;-122.4000351 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -TRANSP:TRANSPARENT -UID:item-98dfcb0bcfdcffcce9c58a84947212ed67cadda6@tripit.com -DTSTART:20111025T163600Z -DTEND:20111025T173600Z -SUMMARY:Directions from SFO to Sofitel San Francisco Bay -LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Directions] 10/25/2011 9:36am - Directions from SF - O to Sofitel San Francisco Bay \nfrom: SFO \nto: 223 Twin Dolphin Drive\, - Redwood City\, CA\, 94065 \nView directions here: http://maps.google.com/m - aps?output=mobile&saddr=SFO&daddr=223+Twin+Dolphin+Drive%2C+Redwood+City%2 - C+CA%2C+94065 \n \n \n\nTripIt - organize your travel at http://www.tripit - .com -GEO:37.5232475;-122.261296 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-in: Sofitel San Francisco Bay -TRANSP:TRANSPARENT -UID:item-8de3937b336c333faf2d55ad0a41c5ca6cc02393@tripit.com -DTSTART:20111025T220000Z -DTEND:20111025T230000Z -LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Lodging] Sofitel San Francisco Bay\; primary guest - John Doe\; conf #F80-0GMW \n223 Twin Dolphin Drive\, Redwood Ci - ty\, CA\, 94065\; tel (+1)650/598-9000 \narrive 10/25/2011\; depart 10/27/ - 2011\; rooms: 1 \nBooked on http://www.sofitel.com/\; http://www.sofitel.c - om/\; Total Cost: 564.00 USD \n \n \n\nTripIt - organize your travel at ht - tp://www.tripit.com -GEO:37.5232475;-122.261296 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-out: Sofitel San Francisco Bay -TRANSP:TRANSPARENT -UID:item-f3ade58646964bde101616a6d26ea7784a1a81e8@tripit.com -DTSTART:20111027T190000Z -DTEND:20111027T200000Z -LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Lodging] Sofitel San Francisco Bay\; primary guest - John Doe\; conf #F80-0GMW \n223 Twin Dolphin Drive\, Redwood Ci - ty\, CA\, 94065\; tel (+1)650/598-9000 \narrive 10/25/2011\; depart 10/27/ - 2011\; rooms: 1 \nBooked on http://www.sofitel.com/\; http://www.sofitel.c - om/\; Total Cost: 564.00 USD \n \n \n\nTripIt - organize your travel at ht - tp://www.tripit.com -GEO:37.5232475;-122.261296 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Drop-off Rental Car: Hertz -TRANSP:TRANSPARENT -UID:item-50620273fea0614d37775649034d5e1de92ae361@tripit.com -DTSTART:20111028T020000Z -DTEND:20111028T030000Z -LOCATION:780 McDonnell Road\, San Francisco\, CA\, 94128 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Car Rental] Hertz\; San Francisco International Ai - rport\; primary driver John Doe\; conf #F2633064194 \n780 McDonn - ell Road\, San Francisco\, CA\, 94128 \npickup 10/25/2011 9:30am\; dropoff - 10/27/2011 7:00pm \nToyota Corolla or similar\; 84.57 USD \nBooked on htt - p://www.hertz.com/\; Reference #: F2633064194\; http://www.hertz.com/\; 80 - 0-654-3131\; Booking Rate: 84.57 USD\; Total Cost: 333.76 USD \n \n \n\nTr - ipIt - organize your travel at http://www.tripit.com -GEO:37.6297569;-122.4000351 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111028T051900Z -SUMMARY:CO6256 SFO to PHX -LOCATION:San Francisco (SFO) -UID:item-71d327f30d8beeaf7bf50c8fa63ce16005b9b0df@tripit.com -DTSTART:20111028T031900Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24259445\n \n[Flight] 10/27/2011 Continental Airlines(CO) #6256 - dep SFO 8:19pm PDT arr PHX 10:19pm MST\; John Doe Ticket #037871 - 7202638\; seat(s) 17D\; conf #A44XS5\, PRX98G\, FYYJZ4(Operated by United - Airlines flight 6256) \nBooked on http://www.americanexpress-travel.com/\; - Reference #: 7128 8086 8504\; http://www.americanexpress-travel.com/\; US - :1-800-297-2977\, Outside:210-582-2716\; Total Cost: $699.99 \n \n \n\nTri - pIt - organize your travel at http://www.tripit.com -GEO:33.436111;-112.009444 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -UID:2d4b446e63a94ade7dab0f0e9546b2d1965f011c@tripit.com -DTSTART;VALUE=DATE:20111108 -DTEND;VALUE=DATE:20111111 -SUMMARY:Redwood City\, CA\, November 2011 -LOCATION:Redwood City\, CA -GEO:37.485215;-122.236355 -TRANSP:TRANSPARENT -DESCRIPTION:John Doe is in Redwood City\, CA from Nov 8 to Nov 1 - 0\, 2011\nView and/or edit details in TripIt : http://www.tripit.com/trip/ - show/id/24913749\nTripIt - organize your travel at http://www.tripit.com\n -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111108T175700Z -SUMMARY:US403 PHX to SFO -LOCATION:Phoenix (PHX) -UID:item-7de7d829b2f95991de6d01c3d68f24b84770168c@tripit.com -DTSTART:20111108T154500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24913749\n \n[Flight] 11/8/2011 US Airways(US) #403 dep PHX 8:45 - am MST arr SFO 9:57am PST\; John Doe\; seat(s) 21C\; conf #FJDX0 - J\, I2W8HW \nBooked on http://www.americanexpress-travel.com/\; Reference - #: 4129 9623 4732\; http://www.americanexpress-travel.com/\; US:1-800-297- - 2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at htt - p://www.tripit.com -GEO:37.618889;-122.375 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Pick-up Rental Car: Dollar Rent A Car -TRANSP:TRANSPARENT -UID:item-1ac6982fefdd79bc5ea849785f415a6291c450b1@tripit.com -DTSTART:20111108T182700Z -DTEND:20111108T192700Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24913749\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte - rnational Airport\; primary driver John Doe\; conf #Q0058133 \np - ickup 11/8/2011 10:27am\; dropoff 11/10/2011 6:25pm \nEconomy \nBooked on - http://www.americanexpress-travel.com/\; Reference #: 4129 9623 4732\; htt - p://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582- - 2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-in: Sofitel San Francisco Bay -TRANSP:TRANSPARENT -UID:item-126e584ffbefbec32a15ca503f0bdf8d3f9cc2f4@tripit.com -DTSTART:20111108T195700Z -DTEND:20111108T205700Z -LOCATION:223 TWIN DOLPHIN DR\, Redwood City\, CA\, 94065-1514 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24913749\n \n[Lodging] Sofitel San Francisco Bay\; primary guest - John Doe\; conf #Q0058133 \n223 TWIN DOLPHIN DR\, Redwood City\ - , CA\, 94065-1514\; tel 1.650.598.9000 \narrive 11/8/2011\; depart 11/10/2 - 011\; rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Refere - nce #: 4129 9623 4732\; http://www.americanexpress-travel.com/\; US:1-800- - 297-2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at - http://www.tripit.com -GEO:37.5232475;-122.261296 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-out: Sofitel San Francisco Bay -TRANSP:TRANSPARENT -UID:item-ff48c502022356ccaa862ebb61761a0de08a1ce9@tripit.com -DTSTART:20111111T015500Z -DTEND:20111111T025500Z -LOCATION:223 TWIN DOLPHIN DR\, Redwood City\, CA\, 94065-1514 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24913749\n \n[Lodging] Sofitel San Francisco Bay\; primary guest - John Doe\; conf #Q0058133 \n223 TWIN DOLPHIN DR\, Redwood City\ - , CA\, 94065-1514\; tel 1.650.598.9000 \narrive 11/8/2011\; depart 11/10/2 - 011\; rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Refere - nce #: 4129 9623 4732\; http://www.americanexpress-travel.com/\; US:1-800- - 297-2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at - http://www.tripit.com -GEO:37.5232475;-122.261296 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Drop-off Rental Car: Dollar Rent A Car -TRANSP:TRANSPARENT -UID:item-c0273c03ddbb68a9b05d5d43a489bc318136ca42@tripit.com -DTSTART:20111111T022500Z -DTEND:20111111T032500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24913749\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte - rnational Airport\; primary driver John Doe\; conf #Q0058133 \np - ickup 11/8/2011 10:27am\; dropoff 11/10/2011 6:25pm \nEconomy \nBooked on - http://www.americanexpress-travel.com/\; Reference #: 4129 9623 4732\; htt - p://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582- - 2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111111T055400Z -SUMMARY:CO496 SFO to PHX -LOCATION:San Francisco (SFO) -UID:item-3473cf9275326ac393b37859df3b04306b4849aa@tripit.com -DTSTART:20111111T035500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/24913749\n \n[Flight] 11/10/2011 Continental Airlines(CO) #496 d - ep SFO 7:55pm PST arr PHX 10:54pm MST\; John Doe\; seat(s) 26B\; - conf #FJDX0J\, I2W8HW(Operated by United Airlines flight 496) \nBooked on - http://www.americanexpress-travel.com/\; Reference #: 4129 9623 4732\; ht - tp://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582 - -2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -GEO:33.436111;-112.009444 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -UID:4ee5ded058432990e3d8808f48ca851e04923b6d@tripit.com -DTSTART;VALUE=DATE:20111129 -DTEND;VALUE=DATE:20111202 -SUMMARY:Milpitas\, CA\, November 2011 -LOCATION:Milpitas\, CA -GEO:37.428272;-121.906624 -TRANSP:TRANSPARENT -DESCRIPTION:John Doe is in Milpitas\, CA from Nov 29 to Dec 1\, - 2011\nView and/or edit details in TripIt : http://www.tripit.com/trip/show - /id/25671681\nTripIt - organize your travel at http://www.tripit.com\n -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111129T172400Z -SUMMARY:US282 PHX to SJC -LOCATION:Phoenix (PHX) -UID:item-644d5973b50d521d50e475ccf5321605d54bd0d5@tripit.com -DTSTART:20111129T152500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/25671681\n \n[Flight] 11/29/2011 US Airways(US) #282 dep PHX 8:2 - 5am MST arr SJC 9:24am PST\; John Doe\; seat(s) 17C\; conf #DQKD - GY \nBooked on http://www.americanexpress-travel.com/\; Reference #: 4131 - 3301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2977\, O - utside:210-582-2716 \n \n \n\nTripIt - organize your travel at http://www. - tripit.com -GEO:37.361111;-121.925556 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Pick-up Rental Car: Alamo -TRANSP:TRANSPARENT -UID:item-10368bbdbc9b6f26f83098500633cc4eb604c751@tripit.com -DTSTART:20111129T175400Z -DTEND:20111129T185400Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/25671681\n \n[Car Rental] Alamo\; San Jose International Airport - \; primary driver John Doe\; conf #372828149COUNT \npickup 11/29 - /2011 9:54am\; dropoff 12/1/2011 5:45pm \nIntermediate \nBooked on http:// - www.americanexpress-travel.com/\; Reference #: 4131 3301 9911\; http://www - .americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n - \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-in: The Beverly Heritage Hotel -TRANSP:TRANSPARENT -UID:item-98d8638d3f1c011d03cb8f58b3a14a0f1203339b@tripit.com -DTSTART:20111129T192400Z -DTEND:20111129T202400Z -LOCATION:1820 Barber Lane\, Milpitas\, CA\, 95035 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/25671681\n \n[Lodging] The Beverly Heritage Hotel\; primary gues - t John Doe\; conf #372828149COUNT \n1820 Barber Lane\, Milpitas\ - , CA\, 95035\; tel 1.408.943.9080 \narrive 11/29/2011\; depart 12/1/2011\; - rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Reference # - : 4131 3301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2 - 977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at http - ://www.tripit.com -GEO:37.4010467;-121.9116284 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111201T194400Z -SUMMARY:US273 SJC to PHX -LOCATION:San Jose (SJC) -UID:item-7b9ee9bb4edfe69743e32b33f9be55753956a883@tripit.com -DTSTART:20111201T175900Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/25671681\n \n[Flight] 12/1/2011 US Airways(US) #273 dep SJC 9:59 - am PST arr PHX 12:44pm MST\; John Doe Ticket #0378727451156\; co - nf #EMF71T \nBooked on http://www.americanexpress-travel.com/\; Reference - #: 5133 5264 1627\; http://www.americanexpress-travel.com/\; US:1-800-297- - 2977\, Outside:210-582-2716\; Total Cost: $316.69 \n \n \n\nTripIt - organ - ize your travel at http://www.tripit.com -GEO:33.436111;-112.009444 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-out: The Beverly Heritage Hotel -TRANSP:TRANSPARENT -UID:item-f79f203072002b8f06598dcb2be0e36af17b625b@tripit.com -DTSTART:20111202T011500Z -DTEND:20111202T021500Z -LOCATION:1820 Barber Lane\, Milpitas\, CA\, 95035 -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/25671681\n \n[Lodging] The Beverly Heritage Hotel\; primary gues - t John Doe\; conf #372828149COUNT \n1820 Barber Lane\, Milpitas\ - , CA\, 95035\; tel 1.408.943.9080 \narrive 11/29/2011\; depart 12/1/2011\; - rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Reference # - : 4131 3301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2 - 977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at http - ://www.tripit.com -GEO:37.4010467;-121.9116284 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Drop-off Rental Car: Alamo -TRANSP:TRANSPARENT -UID:item-69f526ad49fa8ca0a74486f4fc77cc3f9d23a72f@tripit.com -DTSTART:20111202T014500Z -DTEND:20111202T024500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/25671681\n \n[Car Rental] Alamo\; San Jose International Airport - \; primary driver John Doe\; conf #372828149COUNT \npickup 11/29 - /2011 9:54am\; dropoff 12/1/2011 5:45pm \nIntermediate \nBooked on http:// - www.americanexpress-travel.com/\; Reference #: 4131 3301 9911\; http://www - .americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n - \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111202T045900Z -SUMMARY:US288 SJC to PHX -LOCATION:San Jose (SJC) -UID:item-dab68a87c8dd49064ab0ba1dec5ba75ba46ff1d3@tripit.com -DTSTART:20111202T031500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/25671681\n \n[Flight] 12/1/2011 US Airways(US) #288 dep SJC 7:15 - pm PST arr PHX 9:59pm MST\; John Doe\; seat(s) 13C\; conf #DQKDG - Y \nBooked on http://www.americanexpress-travel.com/\; Reference #: 4131 3 - 301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2977\, Ou - tside:210-582-2716 \n \n \n\nTripIt - organize your travel at http://www.t - ripit.com -GEO:33.436111;-112.009444 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -UID:67d48ddde166a2e9bbac2cf7d93fe493b0860008@tripit.com -DTSTART;VALUE=DATE:20111213 -DTEND;VALUE=DATE:20111216 -SUMMARY:San Jose\, CA\, December 2011 -LOCATION:San Jose\, CA -GEO:37.339386;-121.894955 -TRANSP:TRANSPARENT -DESCRIPTION:John Doe is in San Jose\, CA from Dec 13 to Dec 15\, - 2011\nView and/or edit details in TripIt : http://www.tripit.com/trip/sho - w/id/27037117\nTripIt - organize your travel at http://www.tripit.com\n -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111213T172400Z -SUMMARY:US282 PHX to SJC -LOCATION:Phoenix (PHX) -UID:item-2b1b9021be548a87dd335f190b60ab78c33b619d@tripit.com -DTSTART:20111213T152500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27037117\n \n[Flight] 12/13/2011 US Airways(US) #282 dep PHX 8:2 - 5am MST arr SJC 9:24am PST\; John Doe Ticket #0378728465928\; se - at(s) 15C\; conf #GGNV29 \nBooked on http://www.americanexpress-travel.com - /\; Reference #: 3134 0525 5102\; http://www.americanexpress-travel.com/\; - US:1-800-297-2977\, Outside:210-582-2716\; Total Cost: $406.39 \n \n \n\n - TripIt - organize your travel at http://www.tripit.com -GEO:37.361111;-121.925556 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Pick-up Rental Car: Advantage -TRANSP:TRANSPARENT -UID:item-619d345bb08aaef68e8767b672277243697f5bff@tripit.com -DTSTART:20111213T180000Z -DTEND:20111213T190000Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27037117\n \n[Car Rental] Advantage\; San Jose International Air - port\; primary driver John Doe\; conf #F31539020E7 \npickup 12/1 - 3/2011 10:00am\; dropoff 12/15/2011 7:00pm \nStandard Convertible \nRefere - nce #: 3134 0526 3890 \n \n \n\nTripIt - organize your travel at http://ww - w.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-in: Crestview Hotel: -TRANSP:TRANSPARENT -UID:item-fbe6c08e7523c82fac69b40ad1d0899f3d8d5982@tripit.com -DTSTART:20111213T192400Z -DTEND:20111213T202400Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27037117\n \n[Lodging] Crestview Hotel:\; conf #CR31342159 \ntel - 650-966-8848 \narrive 12/13/2011\; depart 12/15/2011 \nBooking Rate: 153. - 30 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-out: Crestview Hotel: -TRANSP:TRANSPARENT -UID:item-7ed8b84628e650a6b37161c7825bac9e72add49f@tripit.com -DTSTART:20111216T011500Z -DTEND:20111216T021500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27037117\n \n[Lodging] Crestview Hotel:\; conf #CR31342159 \ntel - 650-966-8848 \narrive 12/13/2011\; depart 12/15/2011 \nBooking Rate: 153. - 30 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Drop-off Rental Car: Advantage -TRANSP:TRANSPARENT -UID:item-623b54ebe07ffd48845f1a120a86940ce79c698b@tripit.com -DTSTART:20111216T030000Z -DTEND:20111216T040000Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27037117\n \n[Car Rental] Advantage\; San Jose International Air - port\; primary driver John Doe\; conf #F31539020E7 \npickup 12/1 - 3/2011 10:00am\; dropoff 12/15/2011 7:00pm \nStandard Convertible \nRefere - nce #: 3134 0526 3890 \n \n \n\nTripIt - organize your travel at http://ww - w.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20111216T045900Z -SUMMARY:US288 SJC to PHX -LOCATION:San Jose (SJC) -UID:item-52481e672972d2e88d5eaa5cf49bb801562c6014@tripit.com -DTSTART:20111216T031500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27037117\n \n[Flight] 12/15/2011 US Airways(US) #288 dep SJC 7:1 - 5pm PST arr PHX 9:59pm MST\; John Doe Ticket #0378728465928\; se - at(s) 7B\; conf #GGNV29 \nBooked on http://www.americanexpress-travel.com/ - \; Reference #: 3134 0525 5102\; http://www.americanexpress-travel.com/\; - US:1-800-297-2977\, Outside:210-582-2716\; Total Cost: $406.39 \n \n \n\nT - ripIt - organize your travel at http://www.tripit.com -GEO:33.436111;-112.009444 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -UID:7299ff29daed7d5c3e2ed4acc74deec5b7942bd5@tripit.com -DTSTART;VALUE=DATE:20120103 -DTEND;VALUE=DATE:20120106 -SUMMARY:San Francisco\, CA\, January 2012 -LOCATION:San Francisco\, CA -GEO:37.774929;-122.419415 -TRANSP:TRANSPARENT -DESCRIPTION:John Doe is in San Francisco\, CA from Jan 3 to Jan - 5\, 2012\nView and/or edit details in TripIt : http://www.tripit.com/trip/ - show/id/27863159\nTripIt - organize your travel at http://www.tripit.com\n -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20120103T175700Z -SUMMARY:US403 PHX to SFO -LOCATION:Phoenix (PHX) -UID:item-f099e76114bf43ef3b122432579d8b40995412a7@tripit.com -DTSTART:20120103T154500Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27863159\n \n[Flight] 1/3/2012 US Airways(US) #403 dep PHX 8:45a - m MST arr SFO 9:57am PST\; John Doe Ticket #0378731791515\; conf - #FH9B72\, L4F9M5 \nBooked on http://www.americanexpress-travel.com/\; Ref - erence #: 6135 7391 6119\; http://www.americanexpress-travel.com/\; US:1-8 - 00-297-2977\, Outside:210-582-2716\; Total Cost: $668.39 \n \n \n\nTripIt - - organize your travel at http://www.tripit.com -GEO:37.618889;-122.375 -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Pick-up Rental Car: Alamo -TRANSP:TRANSPARENT -UID:item-fae4b4b07b66fc87df125238e0aaf645106cf4f3@tripit.com -DTSTART:20120103T180000Z -DTEND:20120103T190000Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27863159\n \n[Car Rental] Alamo\; San Francisco International Ai - rport\; primary driver John Doe\; conf #373525981COUNT \npickup - 1/3/2012 10:00am\; dropoff 1/5/2012 6:00pm \nCompact \nReference #: 6135 7 - 391 6898 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-in: Grand Hotel Sunnyvale -TRANSP:TRANSPARENT -UID:item-d89a856eb9da9dfdcb4da46f42e49af3a838fcbb@tripit.com -DTSTART:20120103T195700Z -DTEND:20120103T205700Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27863159\n \n[Lodging] Grand Hotel Sunnyvale\; conf #22084SY0361 - 18 \ntel 1-408-7208500 \narrive 1/3/2012\; depart 1/5/2012 \nBooking Rate: - USD 169.00 \nPolicies: Guarantee to valid form of payment is required at - time of booking\; Cancel 1 day prior to arrival date to avoid penalty of 1 - Nights Room Charge. Change fee may apply for early departures and changes - made to confirmed reservations.\; \n \n \n\nTripIt - organize your travel - at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Check-out: Grand Hotel Sunnyvale -TRANSP:TRANSPARENT -UID:item-6edc82f6411fd0b66f2f7f6baafa41623a8623a9@tripit.com -DTSTART:20120106T010900Z -DTEND:20120106T020900Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27863159\n \n[Lodging] Grand Hotel Sunnyvale\; conf #22084SY0361 - 18 \ntel 1-408-7208500 \narrive 1/3/2012\; depart 1/5/2012 \nBooking Rate: - USD 169.00 \nPolicies: Guarantee to valid form of payment is required at - time of booking\; Cancel 1 day prior to arrival date to avoid penalty of 1 - Nights Room Charge. Change fee may apply for early departures and changes - made to confirmed reservations.\; \n \n \n\nTripIt - organize your travel - at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -SUMMARY:Drop-off Rental Car: Alamo -TRANSP:TRANSPARENT -UID:item-58a31b96066ffd09b800af49de59a84f7b7a3a06@tripit.com -DTSTART:20120106T020000Z -DTEND:20120106T030000Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27863159\n \n[Car Rental] Alamo\; San Francisco International Ai - rport\; primary driver John Doe\; conf #373525981COUNT \npickup - 1/3/2012 10:00am\; dropoff 1/5/2012 6:00pm \nCompact \nReference #: 6135 7 - 391 6898 \n \n \n\nTripIt - organize your travel at http://www.tripit.com -END:VEVENT -BEGIN:VEVENT -DTSTAMP:20120101T215311Z -DTEND:20120106T050500Z -SUMMARY:CO496 SFO to PHX -LOCATION:San Francisco (SFO) -UID:item-7884351ce42d503b90ccc48c33c7c30bd4f44767@tripit.com -DTSTART:20120106T030900Z -DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri - p/show/id/27863159\n \n[Flight] 1/5/2012 Continental Airlines(CO) #496 dep - SFO 7:09pm PST arr PHX 10:05pm MST\; John Doe Ticket #037873179 - 1515\; conf #FH9B72\, L4F9M5(Operated by United Airlines flight 496) \nBoo - ked on http://www.americanexpress-travel.com/\; Reference #: 6135 7391 611 - 9\; http://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:2 - 10-582-2716\; Total Cost: $668.39 \n \n \n\nTripIt - organize your travel - at http://www.tripit.com -GEO:33.436111;-112.009444 -END:VEVENT -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test5.ics b/modules/default/calendar/vendor/ical.js/test/test5.ics deleted file mode 100644 index c51f25eec4..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test5.ics +++ /dev/null @@ -1,41 +0,0 @@ -BEGIN:VCALENDAR -VERSION:2.0 -PRODID:-//Meetup//RemoteApi//EN -CALSCALE:GREGORIAN -METHOD:PUBLISH -X-ORIGINAL-URL:http://www.meetup.com/events/ical/8333638/dfdba2e469216075 - 3404f737feace78d526ff0ce/going -X-WR-CALNAME:My Meetups -X-MS-OLK-FORCEINSPECTOROPEN:TRUE -BEGIN:VTIMEZONE -TZID:America/Phoenix -TZURL:http://tzurl.org/zoneinfo-outlook/America/Phoenix -X-LIC-LOCATION:America/Phoenix -BEGIN:STANDARD -TZOFFSETFROM:-0700 -TZOFFSETTO:-0700 -TZNAME:MST -DTSTART:19700101T000000 -END:STANDARD -END:VTIMEZONE -BEGIN:VEVENT -DTSTAMP:20111106T155927Z -DTSTART;TZID=America/Phoenix:20111109T190000 -DTEND;TZID=America/Phoenix:20111109T210000 -STATUS:CONFIRMED -SUMMARY:Phoenix Drupal User Group Monthly Meetup -DESCRIPTION:Phoenix Drupal User Group\nWednesday\, November 9 at 7:00 PM\ - n\nCustomizing node display with template pages in Drupal 6\n\n Jon Shee - han and Matthew Berry of the Office of Knowledge Enterprise Development - (OKED) Knowledge...\n\nDetails: http://www.meetup.com/Phoenix-Drupal-Use - r-Group/events/33627272/ -CLASS:PUBLIC -CREATED:20100630T083023Z -GEO:33.56;-111.90 -LOCATION:Open Source Project Tempe (1415 E University Dr. #103A\, Tempe\, - AZ 85281) -URL:http://www.meetup.com/Phoenix-Drupal-User-Group/events/33627272/ -LAST-MODIFIED:20111102T213309Z -UID:event_nsmxnyppbfc@meetup.com -END:VEVENT -END:VCALENDAR \ No newline at end of file diff --git a/modules/default/calendar/vendor/ical.js/test/test6.ics b/modules/default/calendar/vendor/ical.js/test/test6.ics deleted file mode 100644 index 3762d02b9f..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test6.ics +++ /dev/null @@ -1,1170 +0,0 @@ -BEGIN:VCALENDAR -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110804T120000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:All Areas -SUMMARY:foobar Summer 2011 starts! -URL:F -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110804T120000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:Main entrance -SUMMARY:Main entrance opened -URL:http://www.foobar.org/summer11/come-to-party/entry-setup -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110804T120000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:Loading entrances #1 and #2 -SUMMARY:Loading doors are opened -URL:http://www.foobar.org/summer11/come-to-party/entry-setup -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110804T120000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:foobarTV -SUMMARY:foobarTV broadcast starts -RRULE:FREQ=WEEKLY;BYDAY=MO,FR;INTERVAL=5;UNTIL=20130130T230000Z -URL:http://www.foobartv.net -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110804T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T180000 -LOCATION:Loading entrances #1 and #2 -SUMMARY:Loading doors close -URL:http://www.foobar.org/summer11/come-to-party/entry-setup -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110805T120000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T120000 -LOCATION:Loading entrance #1 -SUMMARY:Loading doors are opened -URL:http://www.foobar.org/summer11/come-to-party/entry-setup -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110805T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T180000 -LOCATION:Loading entrance #1 -SUMMARY:Loading doors close -URL:http://www.foobar.org/summer11/come-to-party/entry-setup -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_deadline -DTEND;VALUE=DATE:20110804T220000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T220000 -LOCATION:PMS -SUMMARY:Oldskool demo\, individual and 4k intro compo deadline -URL:http://www.foobar.org/summer11/compos/how-to/submit-entry -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_deadline -DTEND;VALUE=DATE:20110805T200000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T200000 -LOCATION:PMS -SUMMARY:Group compo deadline -URL:http://www.foobar.org/summer11/compos/how-to/submit-entry -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110804T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:PMS -SUMMARY:Sign-up for street basketball & Guitar Hero solo guitar -URL:http://www.foobar.org/summer11/compos/gaming-sports -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110805T110000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:PMS -SUMMARY:Sign-up for sports and machine dance compos -URL:http://www.foobar.org/summer11/compos/gaming-sports -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110806T160000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:PMS -SUMMARY:Sign-up for poker tournament -URL:http://www.foobar.org/summer11/compos/sponsored-unofficial/poker -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110804T220000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T200000 -LOCATION:Outside main entrance -SUMMARY:Street basketball -URL:http://www.foobar.org/summer11/compos/sports-competitions/team/#stre - etbasketball -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110805T124500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T123000 -LOCATION:Infodesk -SUMMARY:Sport compos - gather up at the infodesk -URL:http://www.foobar.org/summer11/compos/gaming-sports -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110805T140000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T130000 -LOCATION:Grass fields by Messukeskus -SUMMARY:Disk throwing -URL:http://www.foobar.org/summer11/compos/sports-competitions/individual - /#disk -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110805T140000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T130000 -LOCATION:Grass fields by Messukeskus -SUMMARY:CD throwing -URL:http://www.foobar.org/summer11/compos/sports-competitions/individual - /#cd -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110805T160000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T140000 -LOCATION:Grass fields by Messukeskus -SUMMARY:ASUS soccer tournament -URL:http://www.foobar.org/summer11/compos/sports-competitions/team/#socc - er -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110805T000000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T180000 -LOCATION:Guitar Hero -SUMMARY:Guitar Hero: Guitar tournament - qualifying round #1 -URL:http://www.foobar.org/summer11/compos/gaming-sports/individual -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110805T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T120000 -LOCATION:Guitar Hero -SUMMARY:Guitar Hero: Guitar tournament - qualifying round #2 -URL:http://www.foobar.org/summer11/compos/gaming-sports/individual -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110806T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T120000 -LOCATION:Guitar Hero -SUMMARY:Guitar Hero: Guitar tournament - semifinal -URL:http://www.foobar.org/summer11/compos/gaming-sports/individual -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110807T130000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T120000 -LOCATION:Stage -SUMMARY:Guitar Hero: Guitar Tournament final -URL:http://www.foobar.org/summer11/compos/gaming-sports/individual -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110805T210000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T160000 -LOCATION:Third floor -SUMMARY:Machine Dance tournament -URL:http://www.foobar.org/summer11/compos/gaming-sports/individual/#danc - e -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110807T120000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T110000 -LOCATION:Stage -SUMMARY:Machine Dance tournament finals -URL:http://www.foobar.org/summer11/compos/gaming-sports/individual/#danc - e -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110807T000000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T200000 -LOCATION:Seminar area -SUMMARY:Poker tournament -URL:http://www.foobar.org/summer11/compos/sponsored-unofficial/poker -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110804T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T150000 -LOCATION:Infodesk -SUMMARY:GameDev compo recording - come to Infodesk -URL:http://www.foobar.org/summer11/compos/realtime/gamedev -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_showing -DTEND;VALUE=DATE:20110805T010000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T000000 -LOCATION:Big screen -SUMMARY:GameDev compo -URL:http://www.foobar.org/summer11/compos/realtime/gamedev -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110804T190000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T190000 -LOCATION:Website -SUMMARY:Fast music - sample set released -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#music -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_deadline -DTEND;VALUE=DATE:20110804T203000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T203000 -LOCATION:PMS -SUMMARY:Fast music - deadline -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#music -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T003000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T223000 -LOCATION:Infodesk -SUMMARY:Fast music - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#music -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110805T161500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T153000 -LOCATION:Big screen -SUMMARY:Fast music compo -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#music -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110804T203000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T203000 -LOCATION:Website -SUMMARY:Fast graphics - objectives released -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#graphics -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_deadline -DTEND;VALUE=DATE:20110804T220000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T220000 -LOCATION:PMS -SUMMARY:Fast graphics - deadline -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#graphics -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T001500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T233000 -LOCATION:Infodesk -SUMMARY:Fast graphics - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#graphics -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110805T164500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T163000 -LOCATION:Big screen -SUMMARY:Fast graphics compo -URL:http://www.foobar.org/summer11/compos/sound-vision/fast#graphics -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T021500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T221500 -LOCATION:Infodesk -SUMMARY:Extreme music and Oldskool demo - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/realtime/oldskool -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110805T150000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T110000 -LOCATION:Infodesk -SUMMARY:Extreme music and Oldskool demo - compo entry recording\, come to - Infodesk -URL:http://www.foobar.org/summer11/compos/realtime/oldskool -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T144500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T140000 -LOCATION:Big screen -SUMMARY:Extreme music compo -URL:http://www.foobar.org/summer11/compos/realtime/extreme#music -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T171500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T163000 -LOCATION:Big screen -SUMMARY:Oldskool demo compo -URL:http://www.foobar.org/summer11/compos/realtime/oldskool -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T130000 -LOCATION:Infodesk -SUMMARY:Music compo - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/sound-vision/music#freestyle -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T161500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T153000 -LOCATION:Big screen -SUMMARY:Music compo -URL:http://www.foobar.org/summer11/compos/sound-vision/music#freestyle -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T163000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T140000 -LOCATION:Infodesk -SUMMARY:Graphics compo - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/sound-vision/graphics#freestyl - e -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T151500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T150000 -LOCATION:Big screen -SUMMARY:Graphics compo -URL:http://www.foobar.org/summer11/compos/sound-vision/graphics#freestyl - e -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110805T110000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T090000 -LOCATION:Infodesk -SUMMARY:Real wild demo - recording assistance - come to Infodesk -URL:http://www.foobar.org/summer11/compos/realtime/demo#mobile -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T223000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T203000 -LOCATION:Infodesk -SUMMARY:Real wild demo - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/realtime/demo#mobile -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T181500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T173000 -LOCATION:Big screen -SUMMARY:Real wild demo compo -URL:http://www.foobar.org/summer11/compos/realtime/demo#mobile -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T013000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T220000 -LOCATION:Infodesk -SUMMARY:Short film & Real Wild demo - format conversions help - come to In - fodesk -URL:http://www.foobar.org/summer11/compos/sound-vision/short-film -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110806T123000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T100000 -LOCATION:Infodesk -SUMMARY:Short film - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/sound-vision/short-film -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T204500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T194500 -LOCATION:Big screen -SUMMARY:Short film compo -URL:http://www.foobar.org/summer11/compos/sound-vision/short-film -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110805T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T160000 -LOCATION:Infodesk -SUMMARY:4k intro - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/realtime/demo#64k -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T214500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T210000 -LOCATION:Big screen -SUMMARY:4k intro compo -URL:http://www.foobar.org/summer11/compos/realtime/demo#64k -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110806T010000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T230000 -LOCATION:Infodesk -SUMMARY:64k intro - jury - come to Infodesk -URL:http://www.foobar.org/summer11/compos/realtime/demo#64k -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T224500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T220000 -LOCATION:Big screen -SUMMARY:64k intro compo -URL:http://www.foobar.org/summer11/compos/realtime/demo#64k -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_jury -DTEND;VALUE=DATE:20110806T160000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T130000 -LOCATION:Infodesk -SUMMARY:Demo - jury -URL:http://www.foobar.org/summer11/compos/realtime/demo#demo -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_show -DTEND;VALUE=DATE:20110806T230000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T220000 -LOCATION:Big screen -SUMMARY:Demo compo -URL:http://www.foobar.org/summer11/compos/realtime/demo#demo -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110804T160000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T120000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Brackets D\, E\, F -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110804T210000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T170000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Brackets C\, G\, H -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T020000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T220000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Brackets A\, B -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T140000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T110000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Single elimination 16 players -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T153000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T140000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Single elimination 6 players -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T193000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T180000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Semifinal 1 -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T210000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T193000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Semifinal 2 -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T223000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T210000 -LOCATION:Powerplay -SUMMARY:ASUS ROG Starcraft 2 - Bronze match -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T003000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T230000 -LOCATION:Stage -SUMMARY:ASUS ROG Starcraft 2 - Final -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T160000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T130000 -LOCATION:Game hall -SUMMARY:WCG.fi Starcraft 2 – Brackets -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T193000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T173000 -LOCATION:Game hall -SUMMARY:WCG.fi Starcraft 2 - Single elimination 8 players -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T210000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T200000 -LOCATION:Game hall -SUMMARY:WCG.fi Starcraft 2 - Semifinal 1 -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T220000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T210000 -LOCATION:Game hall -SUMMARY:WCG.fi Starcraft 2 - Semifinal 2 -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110807T003000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T223000 -LOCATION:Game hall -SUMMARY:WCG.fi Starcraft 2 - Bronze match -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110807T023000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T000000 -LOCATION:Stage -SUMMARY:WCG.fi Starcraft 2 - Final -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T003000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T193000 -LOCATION:Game hall -SUMMARY:Brink - Brackets -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T140000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T120000 -LOCATION:Game hall -SUMMARY:Brink - Bronze match -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T190000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T173000 -LOCATION:Stage -SUMMARY:Brink - Final -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T190000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T120000 -LOCATION:Game hall -SUMMARY:Team Fortress 2 - Brackets -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T230000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T210000 -LOCATION:Game hall -SUMMARY:Team Fortress 2 - Semifinal 1 -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T230000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T210000 -LOCATION:Game hall -SUMMARY:Team Fortress 2 - Semifinal 2 -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T170000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T150000 -LOCATION:Game hall -SUMMARY:Team Fortress 2 - Bronze match -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T130000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T110000 -LOCATION:Stage -SUMMARY:Team Fortress 2 - Final -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T003000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T180000 -LOCATION:Game hall -SUMMARY:FIFA 2011 - tournament -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110805T230000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T190000 -LOCATION:Game hall -SUMMARY:NHL 2011 - tournament -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T140000 -LOCATION:Game hall -SUMMARY:Tekken 6 - tournament -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110806T190000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T150000 -LOCATION:Game hall -SUMMARY:Super Street Fighter - tournament -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo_game -DTEND;VALUE=DATE:20110807T060000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T180000 -LOCATION:Own computer place -SUMMARY:Heroes of Newerth - Tournament -URL:http://www.peliliiga.fi -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110804T213000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T210000 -LOCATION:Stage -SUMMARY:Opening ceremony -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T170000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T170000 -LOCATION:PMS -SUMMARY:Voting closes for individual and Game development compos -URL:http://www.foobar.org/summer11/party_manual/intranet/vote -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110806T193000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T183000 -LOCATION:Stage -SUMMARY:Prize ceremony 1 -URL:http://www.foobar.org/summer11/compos/prizes/ -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T120000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T120000 -LOCATION:PMS -SUMMARY:Voting closes -URL:http://www.foobar.org/summer11/party_manual/intranet/vote -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Compo -DTEND;VALUE=DATE:20110807T143000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T140000 -LOCATION:Stage -SUMMARY:Prize ceremony 2 -URL:http://www.foobar.org/summer11/compos/prizes/ -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T150000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T143000 -LOCATION:Stage -SUMMARY:Closing ceremony -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T130000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T110000 -LOCATION:Outside loading door #1 -SUMMARY:Robowar tournament qualifier -URL:http://www.foobar.org/summer11/program/robosota -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T160000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T150000 -LOCATION:Outside loading door #1 -SUMMARY:Robowar tournament final -URL:http://www.foobar.org/summer11/program/robosota -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110804T233000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T220000 -LOCATION:Main stage -SUMMARY:Concert - Machinae Supremacy -URL:http://www.foobar.org/summer11/program/concerts -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110805T220000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T203000 -LOCATION:Main stage -SUMMARY:Concert - Press Play on Tape -URL:http://www.foobar.org/summer11/program/concerts -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110805T143000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T140000 -LOCATION:Stage -SUMMARY:Cosplay event presented by BatMud -URL:http://www.foobar.org/summer11/program/ -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T190000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T140000 -LOCATION:Powerplay -SUMMARY:ASUS presents - Paragon WOW raiding -URL:http://www.foobar.org/summer11/program/ -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110804T184500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T180000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Digital resistance\, East European demo art -URL:http://www.foobar.org/summer11/seminars/sessions#demoart -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110804T194500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T190000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Why Being Poor and Having No Budget is Good For - Making Game -URL:http://www.foobar.org/summer11/seminars/sessions#constraints -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110804T204500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T200000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Remix Culture In The Demoscene -URL:http://www.foobar.org/summer11/seminars/sessions#remix -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110804T214500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110804T210000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - DRM of Pacman -URL:http://www.foobar.org/summer11/seminars/sessions#drmpacman -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T104500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T100000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Perfect harmony: crowdsourcing matches musician - s and sound designers to game developers -URL:http://www.foobar.org/summer11/seminars/sessions#music -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T124500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T120000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Browserscene: Creating demos on the Web -URL:http://www.foobar.org/summer11/seminars/sessions#webgl2 -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T144500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T140000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Fumbling my way through pixel-based effects mad - e learning WebGL a lot easier -URL:http://www.foobar.org/summer11/seminars/sessions#webgl1 -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T154500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T150000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - The Making of RO.ME -URL:http://www.foobar.org/summer11/seminars/sessions#rome -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T164500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T160000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Developing next generation of online games -URL:http://www.foobar.org/summer11/seminars/sessions#nextgenonline -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T174500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T170000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Developing Games for Nokia Phones -URL:http://www.foobar.org/summer11/seminars/sessions#nokia_games -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T184500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T180000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Rocking your socks off with Windows Phone 7 -URL:http://www.foobar.org/summer11/seminars/sessions#wp7 -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T194500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T190000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Wonders of Kinect Windows SDK -URL:http://www.foobar.org/summer11/seminars/sessions#kinect -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T114500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T110000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Basics of demo programming -URL:http://www.foobar.org/summer11/seminars/sessions#demoprogramming -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T124500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T120000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Kajak3D\, an open source multiplatform game eng - ine -URL:http://www.foobar.org/summer11/seminars/sessions#kajak3d -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T134500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T130000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Adventures in multithreaded gameplay coding -URL:http://www.foobar.org/summer11/seminars/sessions#threaded -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T144500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T140000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - The art and design of Ridge Racer Unbounded -URL:http://www.foobar.org/summer11/seminars/sessions#ridgeracer -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T154500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T150000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Future of location based mobile games -URL:http://www.foobar.org/summer11/seminars/sessions#location -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T184500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T180000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Robowar -URL:http://www.foobar.org/summer11/seminars/sessions#robosota -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T100000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T100000 -LOCATION:Loading entrances #1 and #2 -SUMMARY:Loading doors open -URL:http://www.foobar.org/summer11/come-to-party/leaving -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T161500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T161500 -LOCATION:All areas -SUMMARY:Lights go on -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T163000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T163000 -LOCATION:All areas -SUMMARY:Party network goes down -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T170000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T170000 -LOCATION:All areas -SUMMARY:Electricity is cut -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T161500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T161500 -LOCATION:foobarTV -SUMMARY:foobarTV broadcast ends -URL:http://www.foobartv.net -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T180000 -LOCATION:Loading entrances #1\, #2 and #3 -SUMMARY:Loading doors closed -URL:http://www.foobar.org/summer11/come-to-party/leaving -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110807T180000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110807T180000 -LOCATION:All areas -SUMMARY:foobar Summer 2011 is over - see you next year! -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110805T153000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T150000 -LOCATION:Outside main entrance -SUMMARY:RC helicopters: flying demonstration with T-REX 600N -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110805T173000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T170000 -LOCATION:Outside main entrance -SUMMARY:RC helicopters: flying demonstration with T-REX 600N -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T133000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T130000 -LOCATION:Outside main entrance -SUMMARY:RC helicopters: flying demonstration with T-REX 600N -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T163000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T160000 -LOCATION:Outside main entrance -SUMMARY:RC helicopters: flying demonstration with T-REX 600N -URL: -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T164500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T160000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars – All aboard to the Dark side of the Moon (Iron - Sky) -URL:http://www.foobar.org/summer11/seminars/sessions#ironsky -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110806T174500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T170000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars – Angry Birds on the web -URL:http://www.foobar.org/summer11/seminars/sessions#angrybirds -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T230000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T120000 -LOCATION:Pelitalo stand -SUMMARY:Pelitalo events begin -URL:http://pelitalo.nettiareena.fi/foobar/ohjelma/ -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Event -DTEND;VALUE=DATE:20110806T210000 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110806T200000 -LOCATION:Pelitalo stand -SUMMARY:Bomberman tournament -URL:http://pelitalo.nettiareena.fi/foobar/ohjelma/ -END:VEVENT -BEGIN:VEVENT -CATEGORIES:Seminar -DTEND;VALUE=DATE:20110805T134500 -DTSTAMP;VALUE=DATE:20120214T224612 -DTSTART;VALUE=DATE:20110805T130000 -LOCATION:Seminar area -SUMMARY:ARTtech seminars - Deconstructing a browserscene demo -URL:http://www.foobar.org/summer11/seminars/sessions#webgl2 -END:VEVENT -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test7.ics b/modules/default/calendar/vendor/ical.js/test/test7.ics deleted file mode 100644 index 4379cd0e7d..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test7.ics +++ /dev/null @@ -1,16 +0,0 @@ -BEGIN:VCALENDAR -VERSION:2.0 -PRODID:ownCloud Calendar 0.6.3 -X-WR-CALNAME:Fête Nationale - Férié -BEGIN:VEVENT -CREATED:20090502T140513Z -DTSTAMP:20111106T124709Z -UID:FA9831E7-C238-4FEC-95E5-CD46BD466421 -SUMMARY:Fête Nationale - Férié -RRULE:FREQ=YEARLY -DTSTART;VALUE=DATE:20120714 -DTEND;VALUE=DATE:20120715 -TRANSP:OPAQUE -SEQUENCE:5 -END:VEVENT -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test8.ics b/modules/default/calendar/vendor/ical.js/test/test8.ics deleted file mode 100644 index e7b2f50f4b..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test8.ics +++ /dev/null @@ -1,23 +0,0 @@ -BEGIN:VCALENDAR -VERSION:2.0 -PRODID:ownCloud Calendar 0.6.3 -X-WR-CALNAME:Default calendar -BEGIN:VTODO -CREATED;VALUE=DATE-TIME:20130714T092804Z -UID:0aa462f13c -LAST-MODIFIED;VALUE=DATE-TIME:20130714T092804Z -DTSTAMP;VALUE=DATE-TIME:20130714T092804Z -CATEGORIES:Projets -SUMMARY:Migrer le blog -PERCENT-COMPLETE:100 -COMPLETED;VALUE=DATE-TIME;TZID=Europe/Monaco:20130716T105745 -END:VTODO -BEGIN:VTODO -CREATED;VALUE=DATE-TIME:20130714T092912Z -UID:5e05bbcf34 -LAST-MODIFIED;VALUE=DATE-TIME:20130714T092912Z -DTSTAMP;VALUE=DATE-TIME:20130714T092912Z -SUMMARY:Créer test unitaire erreur ical -CATEGORIES:Projets -END:VTODO -END:VCALENDAR diff --git a/modules/default/calendar/vendor/ical.js/test/test9.ics b/modules/default/calendar/vendor/ical.js/test/test9.ics deleted file mode 100644 index 76a1d7b99f..0000000000 --- a/modules/default/calendar/vendor/ical.js/test/test9.ics +++ /dev/null @@ -1,21 +0,0 @@ -BEGIN:VCALENDAR -BEGIN:VEVENT -UID:eb9e1bd2-ceba-499f-be77-f02773954c72 -SUMMARY:Event with an alarm -DESCRIPTION:This is an event with an alarm. -ORGANIZER="mailto:stomlinson@mozilla.com" -DTSTART;TZID="America/Los_Angeles":20130418T110000 -DTEND;TZID="America/Los_Angeles":20130418T120000 -STATUS:CONFIRMED -CLASS:PUBLIC -TRANSP:OPAQUE -LAST-MODIFIED:20130418T175632Z -DTSTAMP:20130418T175632Z -SEQUENCE:3 -BEGIN:VALARM -ACTION:DISPLAY -TRIGGER;RELATED=START:-PT5M -DESCRIPTION:Reminder -END:VALARM -END:VEVENT -END:VCALENDAR From 442f270ee0c7c8029ff7c252e53e47c01142ef11 Mon Sep 17 00:00:00 2001 From: rejas Date: Wed, 17 Jun 2020 21:24:50 +0200 Subject: [PATCH 03/11] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db079ddca1..577024ee76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ _This release is scheduled to be released on 2020-07-01._ - Support multiple instances of calendar module with different config [#1109](/~https://github.com/MichMich/MagicMirror/issues/1109) - Fix the use of "maxNumberOfDays" in the module "weatherforecast" [#2018](/~https://github.com/MichMich/MagicMirror/issues/2018) - Throw error when check_config fails [#1928](/~https://github.com/MichMich/MagicMirror/issues/1928) +- Updated ical library to latest version [#1926](/~https://github.com/MichMich/MagicMirror/issues/1926) ## [2.11.0] - 2020-04-01 From bb9ad3daa948dd1a4693c9b6a487bc737810411d Mon Sep 17 00:00:00 2001 From: rejas Date: Wed, 17 Jun 2020 21:37:49 +0200 Subject: [PATCH 04/11] Use some const/let instead of var --- modules/default/calendar/calendarfetcher.js | 30 ++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 7871312a27..9df87d96c9 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -9,14 +9,14 @@ const fetch = require("node-fetch"); const ical = require("ical"); const moment = require("moment"); -var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) { - var self = this; +const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) { + const self = this; var reloadTimer = null; var events = []; - var fetchFailedCallback = function () {}; - var eventsReceivedCallback = function () {}; + let fetchFailedCallback = function () {}; + let eventsReceivedCallback = function () {}; /* fetchCalendar() * Initiates calendar fetch. @@ -239,7 +239,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntr endDate = endDate.endOf("day"); } - var recurrenceTitle = getTitleFromEvent(curEvent); + const 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. @@ -336,7 +336,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntr /* scheduleTimer() * Schedule the timer for the next update. */ - var scheduleTimer = function () { + const scheduleTimer = function () { clearTimeout(reloadTimer); reloadTimer = setTimeout(function () { fetchCalendar(); @@ -350,14 +350,14 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntr * * return bool - The event is a fullday event. */ - var isFullDayEvent = function (event) { + const isFullDayEvent = function (event) { if (event.start.length === 8 || event.start.dateOnly) { return true; } - var start = event.start || 0; - var startDate = new Date(start); - var end = event.end || 0; + const start = event.start || 0; + const startDate = new Date(start); + const end = event.end || 0; if ((end - start) % (24 * 60 * 60 * 1000) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) { // Is 24 hours, and starts on the middle of the night. return true; @@ -375,9 +375,9 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntr * * return bool - The event should be filtered out */ - var timeFilterApplies = function (now, endDate, filter) { + const timeFilterApplies = function (now, endDate, filter) { if (filter) { - var until = filter.split(" "), + const until = filter.split(" "), value = parseInt(until[0]), increment = until[1].slice("-1") === "s" ? until[1] : until[1] + "s", // Massage the data for moment js filterUntil = moment(endDate.format()).subtract(value, increment); @@ -395,8 +395,8 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntr * * return string - The title of the event, or "Event" if no title is found. */ - var getTitleFromEvent = function (event) { - var title = "Event"; + const getTitleFromEvent = function (event) { + let title = "Event"; if (event.summary) { title = typeof event.summary.val !== "undefined" ? event.summary.val : event.summary; } else if (event.description) { @@ -406,7 +406,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntr return title; }; - var testTitleByFilter = function (title, filter, useRegex, regexFlags) { + const testTitleByFilter = function (title, filter, useRegex, regexFlags) { if (useRegex) { // Assume if leading slash, there is also trailing slash if (filter[0] === "/") { From 7d521ed3cebd7438f2a7f86147e7bcfdce9d3169 Mon Sep 17 00:00:00 2001 From: rejas Date: Thu, 18 Jun 2020 21:54:51 +0200 Subject: [PATCH 05/11] More var -> let/const conversions --- modules/default/calendar/calendarfetcher.js | 89 ++++++++++----------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 9df87d96c9..1ab9e9e721 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -12,8 +12,8 @@ const moment = require("moment"); const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) { const self = this; - var reloadTimer = null; - var events = []; + let reloadTimer = null; + let events = []; let fetchFailedCallback = function () {}; let eventsReceivedCallback = function () {}; @@ -64,11 +64,11 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn for (let k in data) { if (data.hasOwnProperty(k)) { - var event = data[k]; - var now = new Date(); - var today = moment().startOf("day").toDate(); - var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. - var past = today; + const event = data[k]; + const now = new Date(); + const today = moment().startOf("day").toDate(); + const future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. + let past = today; if (includePastEvents) { past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); @@ -76,7 +76,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn // FIXME: Ugly fix to solve the facebook birthday issue. // Otherwise, the recurring events only show the birthday for next year. - var isFacebookBirthday = false; + let isFacebookBirthday = false; if (typeof event.uid !== "undefined") { if (event.uid.indexOf("@facebook.com") !== -1) { isFacebookBirthday = true; @@ -84,13 +84,13 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn } if (event.type === "VEVENT") { - var startDate = eventDate(event, "start"); - var endDate; + let startDate = eventDate(event, "start"); + let endDate; + if (typeof event.end !== "undefined") { endDate = eventDate(event, "end"); } else if (typeof event.duration !== "undefined") { - var dur = moment.duration(event.duration); - endDate = startDate.clone().add(dur); + endDate = startDate.clone().add(moment.duration(event.duration)); } else { if (!isFacebookBirthday) { endDate = startDate; @@ -99,20 +99,20 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn } } - // calculate the duration f the event for use with recurring events. - var duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); + // calculate the duration of the event for use with recurring events. + let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); if (event.start.length === 8) { startDate = startDate.startOf("day"); } - var title = getTitleFromEvent(event); + const title = getTitleFromEvent(event); - var excluded = false, + let excluded = false, dateFilter = null; - for (var f in excludedEvents) { - var filter = excludedEvents[f], + for (let f in excludedEvents) { + let filter = excludedEvents[f], testTitle = title.toLowerCase(), until = null, useRegex = false, @@ -158,13 +158,16 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn continue; } - var location = event.location || false; - var geo = event.geo || false; - var description = event.description || false; + const location = event.location || false; + const geo = event.geo || false; + const description = event.description || false; if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { - var rule = event.rrule; - var addedEvents = 0; + const rule = event.rrule; + let addedEvents = 0; + + const pastMoment = moment(past); + const futureMoment = moment(future); // can cause problems with e.g. birthdays before 1900 if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) { @@ -173,28 +176,24 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn } // For recurring events, get the set of start dates that fall within the range - // of dates we"re looking for. + // of dates we're looking for. // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time - var pastLocal = moment(past).subtract(past.getTimezoneOffset(), "minutes").toDate(); - var futureLocal = moment(future).subtract(future.getTimezoneOffset(), "minutes").toDate(); - var datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); - var dates = datesLocal.map(function (dateLocal) { - var date = moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); - return date; + const pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate(); + const futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate(); + const datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); + const dates = datesLocal.map(function (dateLocal) { + return moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); }); // 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 + // 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 + // 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); - - for (var r in event.recurrences) { + for (let 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) { @@ -204,14 +203,14 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn } // 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]; + for (let d in dates) { + const 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; + const dateKey = date.toISOString().substring(0, 10); + let curEvent = event; + let 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) @@ -221,14 +220,14 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn startDate = moment(date); - // For each date that we"re checking, it"s possible that there is a recurrence override for that one day. + // 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. + // 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; @@ -269,7 +268,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn // end recurring event parsing } else { // Single event. - var fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); + const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); if (includePastEvents) { // Past event is too far in the past, so skip. From 5d4a57591964312c899ccc0d7f011bc8258b7e3f Mon Sep 17 00:00:00 2001 From: rejas Date: Sat, 20 Jun 2020 08:32:54 +0200 Subject: [PATCH 06/11] Undo switch to fetch, use request like ical did --- modules/default/calendar/calendarfetcher.js | 40 +- package-lock.json | 1140 +++++++++++-------- package.json | 2 +- 3 files changed, 656 insertions(+), 526 deletions(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 1ab9e9e721..99192e26c2 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -5,9 +5,9 @@ * MIT Licensed. */ const Log = require("../../../js/logger.js"); -const fetch = require("node-fetch"); const ical = require("ical"); const moment = require("moment"); +const request = require("request"); const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) { const self = this; @@ -30,27 +30,32 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn headers: { "User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (/~https://github.com/MichMich/MagicMirror/)" }, - compress: true + gzip: true }; if (auth) { if (auth.method === "bearer") { - opts.headers.Authorization = `Bearer ${auth.pass}`; + opts.auth = { + bearer: auth.pass + }; } else { - let base64data = Buffer.from(`${auth.user}:${auth.pass}`).toString("base64"); - opts.headers.Authorization = `Basic ${base64data}`; - - // TODO - if (auth.method === "digest") { - //opts.auth.sendImmediately = false; - } + opts.auth = { + user: auth.user, + pass: auth.pass, + sendImmediately: auth.method !== "digest" + }; } } - fetch(url, opts) - .then((response) => response.text()) - .then((rawData) => { - const data = ical.parseICS(rawData); + request(url, opts, function (err, r, requestData) { + if (err) { + fetchFailedCallback(self, err); + scheduleTimer(); + } else if (r.statusCode !== 200) { + fetchFailedCallback(self, r.statusCode + ": " + r.statusMessage); + scheduleTimer(); + } else { + const data = ical.parseICS(requestData); const newEvents = []; // 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 @@ -325,11 +330,8 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn self.broadcastEvents(); scheduleTimer(); - }) - .catch((err) => { - fetchFailedCallback(self, err); - scheduleTimer(); - }); + } + }); }; /* scheduleTimer() diff --git a/package-lock.json b/package-lock.json index bfbf1daf51..b29b7ec4f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,19 +13,19 @@ } }, "@babel/core": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", - "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.0", - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helpers": "^7.9.0", - "@babel/parser": "^7.9.0", - "@babel/template": "^7.8.6", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0", + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", + "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.1", + "@babel/generator": "^7.10.2", + "@babel/helper-module-transforms": "^7.10.1", + "@babel/helpers": "^7.10.1", + "@babel/parser": "^7.10.2", + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.2", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", @@ -36,6 +36,46 @@ "source-map": "^0.5.0" }, "dependencies": { + "@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", + "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.1" + } + }, + "@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", + "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "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" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -59,16 +99,25 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "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" + } } } }, "@babel/generator": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", - "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", + "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", "dev": true, "requires": { - "@babel/types": "^7.9.5", + "@babel/types": "^7.10.2", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -83,113 +132,113 @@ } }, "@babel/helper-function-name": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", - "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", + "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.9.5" + "@babel/helper-get-function-arity": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" } }, "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", + "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.1" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", + "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.1" } }, "@babel/helper-module-imports": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", - "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", + "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.1" } }, "@babel/helper-module-transforms": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", - "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", + "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.6", - "@babel/helper-simple-access": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.6", - "@babel/types": "^7.9.0", + "@babel/helper-module-imports": "^7.10.1", + "@babel/helper-replace-supers": "^7.10.1", + "@babel/helper-simple-access": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1", "lodash": "^4.17.13" } }, "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", + "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.1" } }, "@babel/helper-replace-supers": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", - "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", + "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.6" + "@babel/helper-member-expression-to-functions": "^7.10.1", + "@babel/helper-optimise-call-expression": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" } }, "@babel/helper-simple-access": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", - "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", + "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" } }, "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", + "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.1" } }, "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", + "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", "dev": true }, "@babel/helpers": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", - "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", + "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0" + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" } }, "@babel/highlight": { @@ -231,9 +280,9 @@ } }, "@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", + "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", "dev": true }, "@babel/runtime": { @@ -254,33 +303,124 @@ } }, "@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", + "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6" + "@babel/code-frame": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", + "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.1" + } + }, + "@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", + "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "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" + } + }, + "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" + } + } } }, "@babel/traverse": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", + "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.5", - "@babel/helper-function-name": "^7.9.5", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.5", + "@babel/code-frame": "^7.10.1", + "@babel/generator": "^7.10.1", + "@babel/helper-function-name": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" }, "dependencies": { + "@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", + "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.1" + } + }, + "@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", + "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "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" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -295,16 +435,25 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "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" + } } } }, "@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", + "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.9.5", + "@babel/helper-validator-identifier": "^7.10.1", "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } @@ -440,9 +589,9 @@ } }, "acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==" + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", + "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==" }, "acorn-globals": { "version": "4.3.4", @@ -501,23 +650,7 @@ "ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "requires": { - "type-fest": "^0.11.0" - }, - "dependencies": { - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" - } - } + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" }, "ansi-regex": { "version": "2.1.1", @@ -603,9 +736,9 @@ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" }, "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true }, "asn1": { @@ -649,18 +782,18 @@ "dev": true }, "autoprefixer": { - "version": "9.7.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.6.tgz", - "integrity": "sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.0.tgz", + "integrity": "sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A==", "dev": true, "requires": { - "browserslist": "^4.11.1", - "caniuse-lite": "^1.0.30001039", + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001061", "chalk": "^2.4.2", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.27", - "postcss-value-parser": "^4.0.3" + "postcss": "^7.0.30", + "postcss-value-parser": "^4.1.0" }, "dependencies": { "ansi-styles": { @@ -700,9 +833,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", - "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==" }, "babel-polyfill": { "version": "6.26.0", @@ -985,9 +1118,9 @@ "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" }, "caniuse-lite": { - "version": "1.0.30001045", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001045.tgz", - "integrity": "sha512-Y8o2Iz1KPcD6FjySbk1sPpvJqchgxk/iow0DABpGyzA1UeQAuxh63Xh0Enj5/BrsYbXtCN32JmR4ZxQTCQ6E6A==", + "version": "1.0.30001084", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001084.tgz", + "integrity": "sha512-ftdc5oGmhEbLUuMZ/Qp3mOpzfZLCxPYKcvGv6v2dJJ+8EdqcvZRbAGOiLmkM/PV1QGta/uwBs8/nCl6sokDW6w==", "dev": true }, "caseless": { @@ -1060,11 +1193,6 @@ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", "dev": true }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -1098,18 +1226,11 @@ "resolved": "https://registry.npmjs.org/clarinet/-/clarinet-0.12.4.tgz", "integrity": "sha512-Rx9Zw8KQkoPO3/O2yPRchCZm3cGubCQiRLmmFAlbkDKobUIPP3JYul+bKILR9DIv1gSVwPQSgF8JGGkXzX8Q0w==" }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true }, "cliui": { "version": "4.1.0", @@ -1397,6 +1518,7 @@ "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -1727,9 +1849,9 @@ "dev": true }, "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", "dev": true } } @@ -1855,15 +1977,15 @@ } }, "electron-to-chromium": { - "version": "1.3.414", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.414.tgz", - "integrity": "sha512-UfxhIvED++qLwWrAq9uYVcqF8FdeV9sU2S7qhiHYFODxzXRrd1GZRl/PjITHsTEejgibcWDraD8TQqoHb1aCBQ==", + "version": "1.3.478", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.478.tgz", + "integrity": "sha512-pt9GUDD52uEO9ZXWcG4UuW/HwE8T+a8iFP7K2qqWrHB5wUxbbvCIXGBVpQDDQwSR766Nn4AkmLYxOUNd4Ji5Dw==", "dev": true }, "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "encodeurl": { "version": "1.0.2", @@ -1955,6 +2077,14 @@ "has-binary2": "~1.0.2" } }, + "enquirer": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz", + "integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==", + "requires": { + "ansi-colors": "^3.2.1" + } + }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -2059,21 +2189,22 @@ } }, "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.3.0.tgz", + "integrity": "sha512-dJMVXwfU5PT1cj2Nv2VPPrKahKTGdX+5Dh0Q3YuKt+Y2UhdL2YbzsVaBMyG9HC0tBismlv/r1+eZqs6SMIV38Q==", "requires": { "@babel/code-frame": "^7.0.0", "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.0.0", + "eslint-visitor-keys": "^1.2.0", + "espree": "^7.1.0", + "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", @@ -2082,47 +2213,68 @@ "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", + "levn": "^0.4.1", "lodash": "^4.17.14", "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.3", + "optionator": "^0.9.1", "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", "table": "^5.2.3", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "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==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "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==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "requires": { - "color-convert": "^1.9.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, "debug": { @@ -2133,17 +2285,67 @@ "ms": "^2.1.1" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, "strip-json-comments": { @@ -2152,11 +2354,27 @@ "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==" }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" } } } @@ -2179,44 +2397,44 @@ } }, "eslint-plugin-prettier": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.3.tgz", - "integrity": "sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", + "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" } }, "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "requires": { "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" }, "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz", + "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==", "requires": { - "acorn": "^7.1.1", + "acorn": "^7.2.0", "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" + "eslint-visitor-keys": "^1.2.0" } }, "esprima": { @@ -2225,17 +2443,17 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", - "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "requires": { - "estraverse": "^5.0.0" + "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", - "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==" + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==" } } }, @@ -2392,26 +2610,6 @@ "is-extendable": "^0.1.0" } }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, "extract-zip": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", @@ -2455,9 +2653,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", - "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -2479,9 +2677,9 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fastq": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.7.0.tgz", - "integrity": "sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -2510,14 +2708,6 @@ "sax": "^1.0.0" } }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, "file-entry-cache": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", @@ -2602,9 +2792,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" }, "forever-agent": { "version": "0.6.1", @@ -2745,7 +2935,6 @@ "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", @@ -2792,9 +2981,9 @@ } }, "globby": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz", - "integrity": "sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -2806,9 +2995,9 @@ }, "dependencies": { "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true } } @@ -3335,108 +3524,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, - "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", - "requires": { - "is-promise": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -3574,7 +3661,8 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true }, "is-regex": { "version": "1.0.5", @@ -3867,9 +3955,9 @@ "dev": true }, "known-css-properties": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.18.0.tgz", - "integrity": "sha512-69AgJ1rQa7VvUsd2kpvVq+VeObDuo3zrj0CzM5Slmf6yduQFAI2kXPDQJR2IE/u6MSAUOJrwSzjg5vlz8qcMiw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.19.0.tgz", + "integrity": "sha512-eYboRV94Vco725nKMlpkn3nV2+96p9c3gKXRsYqAJSswSENvBhN7n5L+uDhY58xQa0UukWsDMTGELzmD8Q+wTA==", "dev": true }, "lazystream": { @@ -3944,6 +4032,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -4217,9 +4306,9 @@ "dev": true }, "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, "methods": { @@ -4258,12 +4347,13 @@ "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true }, "min-indent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.0.tgz", - "integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, "minimatch": { @@ -4280,15 +4370,22 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minimist-options": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.0.2.tgz", - "integrity": "sha512-seq4hpWkYSUh1y7NXxzucwAN9yVlBc3Upgdjz8vLCP97jG8kaOmzYrVH/m7tQ1NYD1wdtZbSLfdy4zFmRWuc/w==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" }, "dependencies": { + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -4688,11 +4785,6 @@ } } }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4706,7 +4798,8 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true }, "nocache": { "version": "2.1.0", @@ -4732,12 +4825,13 @@ "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true }, "node-releases": { - "version": "1.1.53", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", - "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", + "version": "1.1.58", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.58.tgz", + "integrity": "sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg==", "dev": true }, "normalize-package-data": { @@ -4906,6 +5000,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, "requires": { "mimic-fn": "^2.1.0" } @@ -4938,6 +5033,7 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -4971,7 +5067,8 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "p-defer": { "version": "1.0.0", @@ -5134,7 +5231,8 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true }, "path-parse": { "version": "1.0.6", @@ -5298,9 +5396,9 @@ "dev": true }, "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -5452,12 +5550,12 @@ } }, "postcss-scss": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.0.0.tgz", - "integrity": "sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz", + "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==", "dev": true, "requires": { - "postcss": "^7.0.0" + "postcss": "^7.0.6" } }, "postcss-selector-parser": { @@ -5478,15 +5576,16 @@ "dev": true }, "postcss-value-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", - "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", "dev": true }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true }, "prettier": { "version": "2.0.5", @@ -5890,9 +5989,9 @@ "dev": true }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" }, "remark": { "version": "12.0.0", @@ -5906,9 +6005,9 @@ } }, "remark-parse": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.1.tgz", - "integrity": "sha512-Ye/5W57tdQZWsfkuVyRq9SUWRgECHnDsMuyUMzdSKpTbNPkZeGtoYfsrkeSi4+Xyl0mhcPPddHITXPcCPHrl3w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.2.tgz", + "integrity": "sha512-eMI6kMRjsAGpMXXBAywJwiwAse+KNpmt+BK55Oofy4KvBZEqUDj6mWbGLJZrujoPIPPxDXzn3T9baRlpsm2jnQ==", "dev": true, "requires": { "ccount": "^1.0.0", @@ -5938,9 +6037,9 @@ } }, "remark-stringify": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.0.0.tgz", - "integrity": "sha512-cABVYVloFH+2ZI5bdqzoOmemcz/ZuhQSH6W6ZNYnLojAUUn3xtX7u+6BpnYp35qHoGr2NFBsERV14t4vCIeW8w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.0.tgz", + "integrity": "sha512-FSPZv1ds76oAZjurhhuV5qXSUSoz6QRPuwYK38S41sLHwg4oB7ejnmZshj7qwjgYLf93kdz6BOX9j5aidNE7rA==", "dev": true, "requires": { "ccount": "^1.0.0", @@ -5994,9 +6093,9 @@ "dev": true }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -6005,7 +6104,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -6015,9 +6114,20 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } } }, "request-promise-core": { @@ -6077,15 +6187,6 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6110,21 +6211,6 @@ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "requires": { "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "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" - } - } } }, "rrule": { @@ -6171,14 +6257,6 @@ "rx-lite": "*" } }, - "rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", - "requires": { - "tslib": "^1.9.0" - } - }, "safe-buffer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", @@ -6279,6 +6357,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -6286,7 +6365,8 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true }, "signal-exit": { "version": "3.0.2", @@ -7030,9 +7110,9 @@ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "stringify-entities": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.0.0.tgz", - "integrity": "sha512-h7NJJIssprqlyjHT2eQt2W1F+MCcNmwPGlKb0bWEdET/3N44QN3QbUF/ueKCgAssyKRZ3Br9rQ7FcXjHr0qLHw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.0.1.tgz", + "integrity": "sha512-Lsk3ISA2++eJYqBMPKcr/8eby1I6L0gP0NlxF8Zja6c05yr/yCYyb2c9PwXjd08Ib3If1vn1rbs1H5ZtVuOfvQ==", "dev": true, "requires": { "character-entities-html4": "^1.0.0", @@ -7090,37 +7170,37 @@ "dev": true }, "stylelint": { - "version": "13.3.3", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.3.3.tgz", - "integrity": "sha512-j8Oio2T1YNiJc6iXDaPYd74Jg4zOa1bByNm/g9/Nvnq4tDPsIjMi46jhRZyPPktGPwjJ5FwcmCqIRlH6PVP8mA==", + "version": "13.6.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.6.1.tgz", + "integrity": "sha512-XyvKyNE7eyrqkuZ85Citd/Uv3ljGiuYHC6UiztTR6sWS9rza8j3UeQv/eGcQS9NZz/imiC4GKdk1EVL3wst5vw==", "dev": true, "requires": { "@stylelint/postcss-css-in-js": "^0.37.1", "@stylelint/postcss-markdown": "^0.36.1", - "autoprefixer": "^9.7.6", + "autoprefixer": "^9.8.0", "balanced-match": "^1.0.0", - "chalk": "^4.0.0", + "chalk": "^4.1.0", "cosmiconfig": "^6.0.0", "debug": "^4.1.1", "execall": "^2.0.0", "file-entry-cache": "^5.0.1", - "get-stdin": "^7.0.0", + "get-stdin": "^8.0.0", "global-modules": "^2.0.0", - "globby": "^11.0.0", + "globby": "^11.0.1", "globjoin": "^0.1.4", "html-tags": "^3.1.0", - "ignore": "^5.1.4", + "ignore": "^5.1.8", "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", - "known-css-properties": "^0.18.0", + "known-css-properties": "^0.19.0", "leven": "^3.1.0", "lodash": "^4.17.15", - "log-symbols": "^3.0.0", + "log-symbols": "^4.0.0", "mathml-tag-names": "^2.1.3", - "meow": "^6.1.0", + "meow": "^7.0.1", "micromatch": "^4.0.2", "normalize-selector": "^0.2.0", - "postcss": "^7.0.27", + "postcss": "^7.0.32", "postcss-html": "^0.36.0", "postcss-less": "^3.1.4", "postcss-media-query-parser": "^0.2.3", @@ -7128,10 +7208,10 @@ "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^4.0.2", "postcss-sass": "^0.4.4", - "postcss-scss": "^2.0.0", + "postcss-scss": "^2.1.1", "postcss-selector-parser": "^6.0.2", "postcss-syntax": "^0.36.2", - "postcss-value-parser": "^4.0.3", + "postcss-value-parser": "^4.1.0", "resolve-from": "^5.0.0", "slash": "^3.0.0", "specificity": "^0.4.1", @@ -7141,7 +7221,7 @@ "sugarss": "^2.0.0", "svg-tags": "^1.0.0", "table": "^5.4.6", - "v8-compile-cache": "^2.1.0", + "v8-compile-cache": "^2.1.1", "write-file-atomic": "^3.0.3" }, "dependencies": { @@ -7162,9 +7242,9 @@ } }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", + "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==", "dev": true }, "camelcase-keys": { @@ -7176,12 +7256,20 @@ "camelcase": "^5.3.1", "map-obj": "^4.0.0", "quick-lru": "^4.0.1" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } } }, "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -7212,6 +7300,12 @@ "ms": "^2.1.1" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7223,9 +7317,9 @@ } }, "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true }, "has-flag": { @@ -7235,9 +7329,9 @@ "dev": true }, "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true }, "indent-string": { @@ -7261,6 +7355,15 @@ "p-locate": "^4.1.0" } }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, "map-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", @@ -7268,22 +7371,24 @@ "dev": true }, "meow": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.0.tgz", - "integrity": "sha512-iIAoeI01v6pmSfObAAWFoITAA4GgiT45m4SmJgoxtZfvI0fyZwhV4d0lTwiUXvAKIPlma05Feb2Xngl52Mj5Cg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz", + "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==", "dev": true, "requires": { "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.1.1", + "arrify": "^2.0.1", + "camelcase": "^6.0.0", + "camelcase-keys": "^6.2.2", "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.0.0", - "minimist-options": "^4.0.1", + "hard-rejection": "^2.1.0", + "minimist-options": "^4.0.2", "normalize-package-data": "^2.5.0", - "read-pkg-up": "^7.0.0", + "read-pkg-up": "^7.0.1", "redent": "^3.0.0", "trim-newlines": "^3.0.0", - "type-fest": "^0.8.1", - "yargs-parser": "^18.1.1" + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" } }, "p-limit": { @@ -7357,6 +7462,14 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "redent": { @@ -7419,6 +7532,12 @@ "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", "dev": true }, + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true + }, "yargs-parser": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", @@ -7427,14 +7546,22 @@ "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } } } } }, "stylelint-config-prettier": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-8.0.1.tgz", - "integrity": "sha512-RcjNW7MUaNVqONhJH4+rtlAE3ow/9SsAM0YWV0Lgu3dbTKdWTa/pQXRdFWgoHWpzUKn+9oBKR5x8JdH+20wmgw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-8.0.2.tgz", + "integrity": "sha512-TN1l93iVTXpF9NJstlvP7nOu9zY2k+mN0NSFQ/VEGz15ZIP9ohdDZTtCWHs5LjctAhSAzaILULGbgiM0ItId3A==", "dev": true }, "stylelint-config-recommended": { @@ -7561,11 +7688,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, "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", @@ -7604,7 +7726,8 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true }, "through2": { "version": "0.2.3", @@ -7619,6 +7742,7 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "requires": { "os-tmpdir": "~1.0.2" } @@ -7658,6 +7782,7 @@ "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==", + "dev": true, "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" @@ -7666,7 +7791,8 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true } } }, @@ -7724,6 +7850,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -7933,9 +8060,9 @@ "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==" }, "valid-url": { "version": "1.0.9", @@ -7967,9 +8094,9 @@ } }, "vfile": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.1.0.tgz", - "integrity": "sha512-BaTPalregj++64xbGK6uIlsurN3BCRNM/P2Pg8HezlGzKd1O9PrwIac6bd9Pdx2uTb0QHoioZ+rXKolbVXEgJg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.1.1.tgz", + "integrity": "sha512-lRjkpyDGjVlBA7cDQhQ+gNcvB1BGaTHYuSOcY3S7OhDmBtnzX95FhtZZDecSTDm6aajFymyve6S5DN4ZHGezdQ==", "dev": true, "requires": { "@types/unist": "^2.0.0", @@ -8075,6 +8202,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "requires": { "isexe": "^2.0.0" } diff --git a/package.json b/package.json index 977a653e27..fb6d0aa49d 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "lodash": "^4.17.15", "module-alias": "^2.2.2", "moment": "latest", - "node-fetch": "^2.6.0", + "request": "^2.88.2", "request": "^2.88.0", "rrule": "^2.6.2", "rrule-alt": "^2.2.8", From b2f71a2ce1f1899905132d56c3bd36557f8f0d53 Mon Sep 17 00:00:00 2001 From: rejas Date: Sat, 20 Jun 2020 08:33:19 +0200 Subject: [PATCH 07/11] Update dependencies --- package.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fb6d0aa49d..b20ab60ddc 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "current-week-number": "^1.0.7", "danger": "^3.1.3", "eslint-config-prettier": "^6.11.0", - "eslint-plugin-prettier": "^3.1.3", + "eslint-plugin-prettier": "^3.1.4", "http-auth": "^3.2.3", "husky": "^4.2.5", "jsdom": "^11.6.2", @@ -56,8 +56,8 @@ "prettier": "^2.0.5", "pretty-quick": "^2.0.1", "spectron": "^8.0.0", - "stylelint": "^13.3.3", - "stylelint-config-prettier": "^8.0.1", + "stylelint": "^13.6.1", + "stylelint-config-prettier": "^8.0.2", "stylelint-config-standard": "^20.0.0", "stylelint-prettier": "^1.1.2" }, @@ -67,7 +67,7 @@ "dependencies": { "colors": "^1.1.2", "console-stamp": "^0.2.9", - "eslint": "^6.8.0", + "eslint": "^7.3.0", "express": "^4.16.2", "express-ipfilter": "^1.0.1", "feedme": "latest", @@ -78,7 +78,6 @@ "module-alias": "^2.2.2", "moment": "latest", "request": "^2.88.2", - "request": "^2.88.0", "rrule": "^2.6.2", "rrule-alt": "^2.2.8", "simple-git": "^1.85.0", From 53363b0618bddefa7c57faff6ab4b855cb433c90 Mon Sep 17 00:00:00 2001 From: rejas Date: Sat, 20 Jun 2020 08:45:03 +0200 Subject: [PATCH 08/11] Simplify return call to make a better diff --- modules/default/calendar/calendarfetcher.js | 448 ++++++++++---------- 1 file changed, 225 insertions(+), 223 deletions(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 99192e26c2..b21516783a 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -51,286 +51,288 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn if (err) { fetchFailedCallback(self, err); scheduleTimer(); + return; } else if (r.statusCode !== 200) { fetchFailedCallback(self, r.statusCode + ": " + r.statusMessage); scheduleTimer(); - } else { - const data = ical.parseICS(requestData); - const newEvents = []; + return; + } - // 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 - const limitFunction = function (date, i) { - return true; - }; + const data = ical.parseICS(requestData); + const newEvents = []; - const eventDate = function (event, time) { - return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); - }; + // 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 + const limitFunction = function (date, i) { + return true; + }; - for (let k in data) { - if (data.hasOwnProperty(k)) { - const event = data[k]; - const now = new Date(); - const today = moment().startOf("day").toDate(); - const future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. - let past = today; + const eventDate = function (event, time) { + return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); + }; - if (includePastEvents) { - past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); - } + for (let k in data) { + if (data.hasOwnProperty(k)) { + const event = data[k]; + const now = new Date(); + const today = moment().startOf("day").toDate(); + const future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. + let past = today; - // FIXME: Ugly fix to solve the facebook birthday issue. - // Otherwise, the recurring events only show the birthday for next year. - let isFacebookBirthday = false; - if (typeof event.uid !== "undefined") { - if (event.uid.indexOf("@facebook.com") !== -1) { - isFacebookBirthday = true; - } - } + if (includePastEvents) { + past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); + } - if (event.type === "VEVENT") { - let startDate = eventDate(event, "start"); - let endDate; + // FIXME: Ugly fix to solve the facebook birthday issue. + // Otherwise, the recurring events only show the birthday for next year. + let isFacebookBirthday = false; + if (typeof event.uid !== "undefined") { + if (event.uid.indexOf("@facebook.com") !== -1) { + isFacebookBirthday = true; + } + } - if (typeof event.end !== "undefined") { - endDate = eventDate(event, "end"); - } else if (typeof event.duration !== "undefined") { - endDate = startDate.clone().add(moment.duration(event.duration)); + if (event.type === "VEVENT") { + let startDate = eventDate(event, "start"); + let endDate; + + if (typeof event.end !== "undefined") { + endDate = eventDate(event, "end"); + } else if (typeof event.duration !== "undefined") { + endDate = startDate.clone().add(moment.duration(event.duration)); + } else { + if (!isFacebookBirthday) { + endDate = startDate; } else { - if (!isFacebookBirthday) { - endDate = startDate; - } else { - endDate = moment(startDate).add(1, "days"); - } + endDate = moment(startDate).add(1, "days"); } + } - // calculate the duration of the event for use with recurring events. - let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); + // calculate the duration of the event for use with recurring events. + let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); - if (event.start.length === 8) { - startDate = startDate.startOf("day"); - } + if (event.start.length === 8) { + startDate = startDate.startOf("day"); + } - const title = getTitleFromEvent(event); + const title = getTitleFromEvent(event); - let excluded = false, - dateFilter = null; + let excluded = false, + dateFilter = null; - for (let f in excludedEvents) { - let filter = excludedEvents[f], - testTitle = title.toLowerCase(), - until = null, - useRegex = false, - regexFlags = "g"; + for (let f in excludedEvents) { + let filter = excludedEvents[f], + testTitle = title.toLowerCase(), + until = null, + useRegex = false, + regexFlags = "g"; - if (filter instanceof Object) { - if (typeof filter.until !== "undefined") { - until = filter.until; - } + if (filter instanceof Object) { + if (typeof filter.until !== "undefined") { + until = filter.until; + } - if (typeof filter.regex !== "undefined") { - useRegex = filter.regex; - } + if (typeof filter.regex !== "undefined") { + useRegex = filter.regex; + } - // If additional advanced filtering is added in, this section - // must remain last as we overwrite the filter object with the - // filterBy string - if (filter.caseSensitive) { - filter = filter.filterBy; - testTitle = title; - } else if (useRegex) { - filter = filter.filterBy; - testTitle = title; - regexFlags += "i"; - } else { - filter = filter.filterBy.toLowerCase(); - } + // If additional advanced filtering is added in, this section + // must remain last as we overwrite the filter object with the + // filterBy string + if (filter.caseSensitive) { + filter = filter.filterBy; + testTitle = title; + } else if (useRegex) { + filter = filter.filterBy; + testTitle = title; + regexFlags += "i"; } else { - filter = filter.toLowerCase(); + filter = filter.filterBy.toLowerCase(); } + } else { + filter = filter.toLowerCase(); + } - if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) { - if (until) { - dateFilter = until; - } else { - excluded = true; - } - break; + if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) { + if (until) { + dateFilter = until; + } else { + excluded = true; } + break; } + } - if (excluded) { - continue; - } + if (excluded) { + continue; + } - const location = event.location || false; - const geo = event.geo || false; - const description = event.description || false; + const location = event.location || false; + const geo = event.geo || false; + const description = event.description || false; - if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { - const rule = event.rrule; - let addedEvents = 0; + if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { + const rule = event.rrule; + let addedEvents = 0; - const pastMoment = moment(past); - const futureMoment = moment(future); + const pastMoment = moment(past); + const futureMoment = moment(future); - // can cause problems with e.g. birthdays before 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); - } + // can cause problems with e.g. birthdays before 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); + } - // For recurring events, get the set of start dates that fall within the range - // of dates we're looking for. - // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time - const pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate(); - const futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate(); - const datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); - const dates = datesLocal.map(function (dateLocal) { - return moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); - }); - - // 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) { - for (let 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)); - } + // For recurring events, get the set of start dates that fall within the range + // of dates we're looking for. + // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time + const pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate(); + const futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate(); + const datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); + const dates = datesLocal.map(function (dateLocal) { + return moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); + }); + + // 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) { + for (let 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 (let d in dates) { - const 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 ) - const dateKey = date.toISOString().substring(0, 10); - let curEvent = event; - let 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; - } - - 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; - } + // Loop through the set of date entries to see which recurrences should be added to our event list. + for (let d in dates) { + const 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 ) + const dateKey = date.toISOString().substring(0, 10); + let curEvent = event; + let 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; + } - endDate = moment(parseInt(startDate.format("x")) + duration, "x"); - if (startDate.format("x") === endDate.format("x")) { - endDate = endDate.endOf("day"); - } + startDate = moment(date); - const recurrenceTitle = getTitleFromEvent(curEvent); + // 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; + } - // 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; - } + endDate = moment(parseInt(startDate.format("x")) + duration, "x"); + if (startDate.format("x") === endDate.format("x")) { + endDate = endDate.endOf("day"); + } - if (timeFilterApplies(now, endDate, dateFilter)) { - showRecurrence = false; - } + const recurrenceTitle = getTitleFromEvent(curEvent); - if (showRecurrence === true && addedEvents < maximumEntries) { - addedEvents++; - newEvents.push({ - title: recurrenceTitle, - startDate: startDate.format("x"), - endDate: endDate.format("x"), - fullDayEvent: isFullDayEvent(event), - class: event.class, - firstYear: event.start.getFullYear(), - location: location, - geo: geo, - description: description - }); - } + // 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; } - // end recurring event parsing - } else { - // Single event. - const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); - if (includePastEvents) { - // Past event is too far in the past, so skip. - if (endDate < past) { - continue; - } - } else { - // It's not a fullday event, and it is in the past, so skip. - if (!fullDayEvent && endDate < new Date()) { - continue; - } - - // It's a fullday event, and it is before today, So skip. - if (fullDayEvent && endDate <= today) { - continue; - } + if (timeFilterApplies(now, endDate, dateFilter)) { + showRecurrence = false; } - // It exceeds the maximumNumberOfDays limit, so skip. - if (startDate > future) { + if (showRecurrence === true && addedEvents < maximumEntries) { + addedEvents++; + newEvents.push({ + title: recurrenceTitle, + startDate: startDate.format("x"), + endDate: endDate.format("x"), + fullDayEvent: isFullDayEvent(event), + class: event.class, + firstYear: event.start.getFullYear(), + location: location, + geo: geo, + description: description + }); + } + } + // end recurring event parsing + } else { + // Single event. + const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); + + if (includePastEvents) { + // Past event is too far in the past, so skip. + if (endDate < past) { continue; } - - if (timeFilterApplies(now, endDate, dateFilter)) { + } else { + // It's not a fullday event, and it is in the past, so skip. + if (!fullDayEvent && endDate < new Date()) { continue; } - // Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already - if (fullDayEvent && startDate <= today) { - startDate = moment(today); + // It's a fullday event, and it is before today, So skip. + if (fullDayEvent && endDate <= today) { + continue; } + } - // Every thing is good. Add it to the list. - newEvents.push({ - title: title, - startDate: startDate.format("x"), - endDate: endDate.format("x"), - fullDayEvent: fullDayEvent, - class: event.class, - location: location, - geo: geo, - description: description - }); + // It exceeds the maximumNumberOfDays limit, so skip. + if (startDate > future) { + continue; } + + if (timeFilterApplies(now, endDate, dateFilter)) { + continue; + } + + // Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already + if (fullDayEvent && startDate <= today) { + startDate = moment(today); + } + + // Every thing is good. Add it to the list. + newEvents.push({ + title: title, + startDate: startDate.format("x"), + endDate: endDate.format("x"), + fullDayEvent: fullDayEvent, + class: event.class, + location: location, + geo: geo, + description: description + }); } } } + } - newEvents.sort(function (a, b) { - return a.startDate - b.startDate; - }); + newEvents.sort(function (a, b) { + return a.startDate - b.startDate; + }); - events = newEvents.slice(0, maximumEntries); + events = newEvents.slice(0, maximumEntries); - self.broadcastEvents(); - scheduleTimer(); - } + self.broadcastEvents(); + scheduleTimer(); }); }; From 7e5bfa8dd2c1d0091bb78409f1941a9d2ae671b8 Mon Sep 17 00:00:00 2001 From: rejas Date: Sat, 20 Jun 2020 08:45:22 +0200 Subject: [PATCH 09/11] Fix slice parameter type --- modules/default/calendar/calendarfetcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index b21516783a..7c44038569 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -382,7 +382,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn if (filter) { const until = filter.split(" "), value = parseInt(until[0]), - increment = until[1].slice("-1") === "s" ? until[1] : until[1] + "s", // Massage the data for moment js + increment = until[1].slice(-1) === "s" ? until[1] : until[1] + "s", // Massage the data for moment js filterUntil = moment(endDate.format()).subtract(value, increment); return now < filterUntil.format("x"); From 1e5bd98f023b441d7548558e2d80618df8956b58 Mon Sep 17 00:00:00 2001 From: rejas Date: Sat, 20 Jun 2020 08:45:46 +0200 Subject: [PATCH 10/11] Make calendar debuger use const stuff and add npm script for it --- modules/default/calendar/debug.js | 23 +++++++++++------------ package.json | 1 + 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/default/calendar/debug.js b/modules/default/calendar/debug.js index cdcbb0247c..f01bcc0dc3 100644 --- a/modules/default/calendar/debug.js +++ b/modules/default/calendar/debug.js @@ -5,24 +5,23 @@ * By Michael Teeuw https://michaelteeuw.nl * MIT Licensed. */ - -var CalendarFetcher = require("./calendarfetcher.js"); - -var url = "https://calendar.google.com/calendar/ical/pkm1t2uedjbp0uvq1o7oj1jouo%40group.calendar.google.com/private-08ba559f89eec70dd74bbd887d0a3598/basic.ics"; // Standard test URL -// var url = "https://www.googleapis.com/calendar/v3/calendars/primary/events/"; // URL for Bearer auth (must be configured in Google OAuth2 first) -var fetchInterval = 60 * 60 * 1000; -var maximumEntries = 10; -var maximumNumberOfDays = 365; -var user = "magicmirror"; -var pass = "MyStrongPass"; -var auth = { +const CalendarFetcher = require("./calendarfetcher.js"); + +const url = "https://calendar.google.com/calendar/ical/pkm1t2uedjbp0uvq1o7oj1jouo%40group.calendar.google.com/private-08ba559f89eec70dd74bbd887d0a3598/basic.ics"; // Standard test URL +//const url = "https://www.googleapis.com/calendar/v3/calendars/primary/events/"; // URL for Bearer auth (must be configured in Google OAuth2 first) +const fetchInterval = 60 * 60 * 1000; +const maximumEntries = 10; +const maximumNumberOfDays = 365; +const user = "magicmirror"; +const pass = "MyStrongPass"; +const auth = { user: user, pass: pass }; console.log("Create fetcher ..."); -var fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth); +const fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth); fetcher.onReceive(function (fetcher) { console.log(fetcher.events()); diff --git a/package.json b/package.json index b20ab60ddc..741d1d2eef 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "test:prettier": "prettier --check **/*.{js,css,json,md,yml}", "test:js": "eslint *.js js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --quiet", "test:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json", + "test:calendar": "node ./modules/default/calendar/debug.js", "config:check": "node js/check_config.js", "lint:prettier": "prettier --write **/*.{js,css,json,md,yml}", "lint:js": "eslint *.js js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --fix", From daa6f5051c125357653f7820d92f2aa23d923e25 Mon Sep 17 00:00:00 2001 From: rejas Date: Sat, 20 Jun 2020 09:01:35 +0200 Subject: [PATCH 11/11] Use object.entries to iterate over data --- modules/default/calendar/calendarfetcher.js | 415 ++++++++++---------- 1 file changed, 206 insertions(+), 209 deletions(-) diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 7c44038569..4e3537cd02 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -70,260 +70,257 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); }; - for (let k in data) { - if (data.hasOwnProperty(k)) { - const event = data[k]; - const now = new Date(); - const today = moment().startOf("day").toDate(); - const future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. - let past = today; - - if (includePastEvents) { - past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); - } + Object.entries(data).forEach(([key, event]) => { + const now = new Date(); + const today = moment().startOf("day").toDate(); + const future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. + let past = today; + + if (includePastEvents) { + past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); + } - // FIXME: Ugly fix to solve the facebook birthday issue. - // Otherwise, the recurring events only show the birthday for next year. - let isFacebookBirthday = false; - if (typeof event.uid !== "undefined") { - if (event.uid.indexOf("@facebook.com") !== -1) { - isFacebookBirthday = true; - } + // FIXME: Ugly fix to solve the facebook birthday issue. + // Otherwise, the recurring events only show the birthday for next year. + let isFacebookBirthday = false; + if (typeof event.uid !== "undefined") { + if (event.uid.indexOf("@facebook.com") !== -1) { + isFacebookBirthday = true; } + } - if (event.type === "VEVENT") { - let startDate = eventDate(event, "start"); - let endDate; - - if (typeof event.end !== "undefined") { - endDate = eventDate(event, "end"); - } else if (typeof event.duration !== "undefined") { - endDate = startDate.clone().add(moment.duration(event.duration)); + if (event.type === "VEVENT") { + let startDate = eventDate(event, "start"); + let endDate; + + if (typeof event.end !== "undefined") { + endDate = eventDate(event, "end"); + } else if (typeof event.duration !== "undefined") { + endDate = startDate.clone().add(moment.duration(event.duration)); + } else { + if (!isFacebookBirthday) { + endDate = startDate; } else { - if (!isFacebookBirthday) { - endDate = startDate; - } else { - endDate = moment(startDate).add(1, "days"); - } + endDate = moment(startDate).add(1, "days"); } + } - // calculate the duration of the event for use with recurring events. - let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); + // calculate the duration of the event for use with recurring events. + let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); - if (event.start.length === 8) { - startDate = startDate.startOf("day"); - } + if (event.start.length === 8) { + startDate = startDate.startOf("day"); + } - const title = getTitleFromEvent(event); + const title = getTitleFromEvent(event); - let excluded = false, - dateFilter = null; + let excluded = false, + dateFilter = null; - for (let f in excludedEvents) { - let filter = excludedEvents[f], - testTitle = title.toLowerCase(), - until = null, - useRegex = false, - regexFlags = "g"; + for (let f in excludedEvents) { + let filter = excludedEvents[f], + testTitle = title.toLowerCase(), + until = null, + useRegex = false, + regexFlags = "g"; - if (filter instanceof Object) { - if (typeof filter.until !== "undefined") { - until = filter.until; - } + if (filter instanceof Object) { + if (typeof filter.until !== "undefined") { + until = filter.until; + } - if (typeof filter.regex !== "undefined") { - useRegex = filter.regex; - } + if (typeof filter.regex !== "undefined") { + useRegex = filter.regex; + } - // If additional advanced filtering is added in, this section - // must remain last as we overwrite the filter object with the - // filterBy string - if (filter.caseSensitive) { - filter = filter.filterBy; - testTitle = title; - } else if (useRegex) { - filter = filter.filterBy; - testTitle = title; - regexFlags += "i"; - } else { - filter = filter.filterBy.toLowerCase(); - } + // If additional advanced filtering is added in, this section + // must remain last as we overwrite the filter object with the + // filterBy string + if (filter.caseSensitive) { + filter = filter.filterBy; + testTitle = title; + } else if (useRegex) { + filter = filter.filterBy; + testTitle = title; + regexFlags += "i"; } else { - filter = filter.toLowerCase(); + filter = filter.filterBy.toLowerCase(); } + } else { + filter = filter.toLowerCase(); + } - if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) { - if (until) { - dateFilter = until; - } else { - excluded = true; - } - break; + if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) { + if (until) { + dateFilter = until; + } else { + excluded = true; } + break; } + } - if (excluded) { - continue; - } + if (excluded) { + return; + } - const location = event.location || false; - const geo = event.geo || false; - const description = event.description || false; + const location = event.location || false; + const geo = event.geo || false; + const description = event.description || false; - if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { - const rule = event.rrule; - let addedEvents = 0; + if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { + const rule = event.rrule; + let addedEvents = 0; - const pastMoment = moment(past); - const futureMoment = moment(future); + const pastMoment = moment(past); + const futureMoment = moment(future); - // can cause problems with e.g. birthdays before 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); - } + // can cause problems with e.g. birthdays before 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); + } - // For recurring events, get the set of start dates that fall within the range - // of dates we're looking for. - // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time - const pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate(); - const futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate(); - const datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); - const dates = datesLocal.map(function (dateLocal) { - return moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); - }); - - // 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) { - for (let 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)); - } + // For recurring events, get the set of start dates that fall within the range + // of dates we're looking for. + // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time + const pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate(); + const futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate(); + const datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); + const dates = datesLocal.map(function (dateLocal) { + return moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); + }); + + // 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) { + for (let 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 (let d in dates) { - const 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 ) - const dateKey = date.toISOString().substring(0, 10); - let curEvent = event; - let 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; - } + // Loop through the set of date entries to see which recurrences should be added to our event list. + for (let d in dates) { + const 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 ) + const dateKey = date.toISOString().substring(0, 10); + let curEvent = event; + let 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; + } - startDate = moment(date); + 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; - } + // 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"); - } + endDate = moment(parseInt(startDate.format("x")) + duration, "x"); + if (startDate.format("x") === endDate.format("x")) { + endDate = endDate.endOf("day"); + } - const recurrenceTitle = getTitleFromEvent(curEvent); + const 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 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 (timeFilterApplies(now, endDate, dateFilter)) { + showRecurrence = false; + } - if (showRecurrence === true && addedEvents < maximumEntries) { - addedEvents++; - newEvents.push({ - title: recurrenceTitle, - startDate: startDate.format("x"), - endDate: endDate.format("x"), - fullDayEvent: isFullDayEvent(event), - class: event.class, - firstYear: event.start.getFullYear(), - location: location, - geo: geo, - description: description - }); - } + if (showRecurrence === true && addedEvents < maximumEntries) { + addedEvents++; + newEvents.push({ + title: recurrenceTitle, + startDate: startDate.format("x"), + endDate: endDate.format("x"), + fullDayEvent: isFullDayEvent(event), + class: event.class, + firstYear: event.start.getFullYear(), + location: location, + geo: geo, + description: description + }); + } + } + // end recurring event parsing + } else { + // Single event. + const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); + + if (includePastEvents) { + // Past event is too far in the past, so skip. + if (endDate < past) { + return; } - // end recurring event parsing } else { - // Single event. - const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); - - if (includePastEvents) { - // Past event is too far in the past, so skip. - if (endDate < past) { - continue; - } - } else { - // It's not a fullday event, and it is in the past, so skip. - if (!fullDayEvent && endDate < new Date()) { - continue; - } - - // It's a fullday event, and it is before today, So skip. - if (fullDayEvent && endDate <= today) { - continue; - } + // It's not a fullday event, and it is in the past, so skip. + if (!fullDayEvent && endDate < new Date()) { + return; } - // It exceeds the maximumNumberOfDays limit, so skip. - if (startDate > future) { - continue; + // It's a fullday event, and it is before today, So skip. + if (fullDayEvent && endDate <= today) { + return; } + } - if (timeFilterApplies(now, endDate, dateFilter)) { - continue; - } + // It exceeds the maximumNumberOfDays limit, so skip. + if (startDate > future) { + return; + } - // Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already - if (fullDayEvent && startDate <= today) { - startDate = moment(today); - } + if (timeFilterApplies(now, endDate, dateFilter)) { + return; + } - // Every thing is good. Add it to the list. - newEvents.push({ - title: title, - startDate: startDate.format("x"), - endDate: endDate.format("x"), - fullDayEvent: fullDayEvent, - class: event.class, - location: location, - geo: geo, - description: description - }); + // Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already + if (fullDayEvent && startDate <= today) { + startDate = moment(today); } + + // Every thing is good. Add it to the list. + newEvents.push({ + title: title, + startDate: startDate.format("x"), + endDate: endDate.format("x"), + fullDayEvent: fullDayEvent, + class: event.class, + location: location, + geo: geo, + description: description + }); } } - } + }); newEvents.sort(function (a, b) { return a.startDate - b.startDate;