Socket
Socket
Sign inDemoInstall

@hebcal/icalendar

Package Overview
Dependencies
Maintainers
1
Versions
92
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hebcal/icalendar - npm Package Compare versions

Comparing version 3.1.1 to 3.2.0

295

dist/index.js

@@ -350,3 +350,3 @@ 'use strict';

var version="3.1.1";
var version="3.2.0";

@@ -418,132 +418,168 @@ const VTIMEZONE = {};

}
const char74re = /(.{1,74})/g;
/**
* @private
* @param {Event} e
* @param {HebrewCalendar.Options} options
* @return {string[]}
* Represents an RFC 2445 iCalendar VEVENT
*/
class IcalEvent {
/**
* Builds an IcalEvent object from a Hebcal Event
* @param {Event} ev
* @param {HebrewCalendar.Options} options
*/
constructor(ev, options) {
const dtstamp = options.dtstamp || makeDtstamp(new Date());
const timed = Boolean(ev.eventTime);
let subj = timed ? renderTitleWithoutTime_1(ev) : ev.render();
const desc = ev.getDesc(); // original untranslated
function eventToIcal0(e, options) {
const dtstamp = options.dtstamp || makeDtstamp(new Date());
const timed = Boolean(e.eventTime);
let subj = timed ? renderTitleWithoutTime_1(e) : e.render();
const desc = e.getDesc(); // original untranslated
const mask = ev.getFlags();
let location;
const mask = e.getFlags();
const candles = desc === 'Havdalah' || desc === 'Candle lighting';
let location;
if (timed && options.location.name) {
const comma = options.location.name.indexOf(',');
location = comma == -1 ? options.location.name : options.location.name.substring(0, comma);
}
if (timed && options.location.name) {
const comma = options.location.name.indexOf(',');
location = comma == -1 ? options.location.name : options.location.name.substring(0, comma);
}
if (mask & core.flags.DAF_YOMI) {
const colon = subj.indexOf(': ');
if (mask & core.flags.DAF_YOMI) {
const colon = subj.indexOf(': ');
if (colon != -1) {
location = subj.substring(0, colon);
subj = subj.substring(colon + 2);
if (colon != -1) {
location = subj.substring(0, colon);
subj = subj.substring(colon + 2);
}
}
}
const date = formatYYYYMMDD(e.getDate().greg());
let startDate = date;
let dtargs;
let endDate;
let transp = 'TRANSPARENT';
let busyStatus = 'FREE';
const date = formatYYYYMMDD(ev.getDate().greg());
let startDate = date;
let dtargs;
let endDate;
let transp = 'TRANSPARENT';
let busyStatus = 'FREE';
if (timed) {
let [hour, minute] = e.eventTimeStr.split(':');
hour = +hour;
minute = +minute;
startDate += 'T' + pad2_1(hour) + pad2_1(minute) + '00';
endDate = startDate;
dtargs = `;TZID=${options.location.tzid}`;
} else {
endDate = formatYYYYMMDD(e.getDate().next().greg()); // for all-day untimed, use DTEND;VALUE=DATE intsead of DURATION:P1D.
// It's more compatible with everthing except ancient versions of
// Lotus Notes circa 2004
if (timed) {
let [hour, minute] = ev.eventTimeStr.split(':');
hour = +hour;
minute = +minute;
startDate += 'T' + pad2_1(hour) + pad2_1(minute) + '00';
endDate = startDate;
dtargs = `;TZID=${options.location.tzid}`;
} else {
endDate = formatYYYYMMDD(ev.getDate().next().greg()); // for all-day untimed, use DTEND;VALUE=DATE intsead of DURATION:P1D.
// It's more compatible with everthing except ancient versions of
// Lotus Notes circa 2004
dtargs = ';VALUE=DATE';
dtargs = ';VALUE=DATE';
if (mask & core.flags.CHAG) {
transp = 'OPAQUE';
busyStatus = 'OOF';
if (mask & core.flags.CHAG) {
transp = 'OPAQUE';
busyStatus = 'OOF';
}
}
}
const digest = murmur3_1(desc).toString(16);
let uid = `hebcal-${date}-${digest}`;
const digest = murmur3_1(desc).toString(16);
let uid = `hebcal-${date}-${digest}`;
if (timed && options.location) {
if (options.location.geoid) {
uid += `-${options.location.geoid}`;
} else if (options.location.name) {
uid += '-' + makeAnchor_1(options.location.name);
if (timed && options.location) {
if (options.location.geoid) {
uid += `-${options.location.geoid}`;
} else if (options.location.name) {
uid += '-' + makeAnchor_1(options.location.name);
}
} // make subject safe for iCalendar
subj = subj.replace(/,/g, '\\,');
if (options.appendHebrewToSubject) {
const hebrew = ev.renderBrief('he');
if (hebrew) {
subj += ` / ${hebrew}`;
}
}
} // make subject safe for iCalendar
const isUserEvent = Boolean(mask & core.flags.USER_EVENT);
const category = isUserEvent ? 'Personal' : 'Holiday';
const arr = ['BEGIN:VEVENT', `DTSTAMP:${dtstamp}`, `CATEGORIES:${category}`, `SUMMARY:${subj}`, `DTSTART${dtargs}:${startDate}`, `DTEND${dtargs}:${endDate}`, `TRANSP:${transp}`, `X-MICROSOFT-CDO-BUSYSTATUS:${busyStatus}`, `UID:${uid}`];
subj = subj.replace(/,/g, '\\,');
if (!isUserEvent) {
arr.push('CLASS:PUBLIC');
} // create memo (holiday descr, Torah, etc)
if (options.appendHebrewToSubject) {
const hebrew = e.renderBrief('he');
if (hebrew) {
subj += ` / ${hebrew}`;
const candles = desc === 'Havdalah' || desc === 'Candle lighting';
const memo = candles ? '' : createMemo(ev, options.il);
addOptional(arr, 'DESCRIPTION', memo);
addOptional(arr, 'LOCATION', location);
if (timed && options.location) {
arr.push('GEO:' + options.location.latitude + ';' + options.location.longitude);
}
}
const isUserEvent = Boolean(mask & core.flags.USER_EVENT);
const category = isUserEvent ? 'Personal' : 'Holiday';
const arr = ['BEGIN:VEVENT', `DTSTAMP:${dtstamp}`, `CATEGORIES:${category}`, `SUMMARY:${subj}`, `DTSTART${dtargs}:${startDate}`, `DTEND${dtargs}:${endDate}`, `TRANSP:${transp}`, `X-MICROSOFT-CDO-BUSYSTATUS:${busyStatus}`, `UID:${uid}`];
let alarm;
if (!isUserEvent) {
arr.push('CLASS:PUBLIC');
} // create memo (holiday descr, Torah, etc)
if (mask & core.flags.OMER_COUNT) {
alarm = '3H'; // 9pm Omer alarm evening before
} else if (isUserEvent) {
alarm = '12H'; // noon the day before
} else if (timed && desc.startsWith('Candle lighting')) {
alarm = '10M'; // ten minutes
}
if (alarm) {
arr.push('BEGIN:VALARM', 'ACTION:DISPLAY', 'DESCRIPTION:REMINDER', `TRIGGER;RELATED=START:-PT${alarm}`, 'END:VALARM');
}
const memo = candles ? '' : createMemo(e, options.il);
addOptional(arr, 'DESCRIPTION', memo);
addOptional(arr, 'LOCATION', location);
arr.push('END:VEVENT');
this.lines = arr;
this.options = options;
this.ev = ev;
}
/**
* @return {string}
*/
if (timed && options.location) {
arr.push('GEO:' + options.location.latitude + ';' + options.location.longitude);
toString() {
return this.getFoldedLines().join('\r\n');
}
/**
* @return {NodeJS.ReadableStream}
*/
let alarm;
if (mask & core.flags.OMER_COUNT) {
alarm = '3H'; // 9pm Omer alarm evening before
} else if (isUserEvent) {
alarm = '12H'; // noon the day before
} else if (timed && desc.startsWith('Candle lighting')) {
alarm = '10M'; // ten minutes
toStream() {
const readable = new stream.Readable();
const lines = this.getFoldedLines();
for (const line of lines) {
readable.push(line);
readable.push('\r\n');
}
readable.push(null);
return readable;
}
/**
* fold lines to 75 characters
* @return {string[]}
*/
if (alarm) {
arr.push('BEGIN:VALARM', 'ACTION:DISPLAY', 'DESCRIPTION:REMINDER', `TRIGGER;RELATED=START:-PT${alarm}`, 'END:VALARM');
getFoldedLines() {
return this.getLines().map(line => {
return line.length <= 74 ? line : line.match(char74re).join('\r\n ');
});
}
/**
* @return {string[]}
*/
arr.push('END:VEVENT');
return arr;
}
const char74re = /(.{1,74})/g;
/**
* @private
* @param {Event} ev
* @param {HebrewCalendar.Options} options
* @return {string[]}
*/
getLines() {
return this.lines;
}
function eventToIcal1(ev, options) {
const lines = eventToIcal0(ev, options); // fold lines to 75 characters
return lines.map(line => {
return line.length <= 74 ? line : line.match(char74re).join('\r\n ');
});
}

@@ -557,6 +593,5 @@ /**

function eventToIcal(ev, options) {
const lines = eventToIcal1(ev, options);
return lines.join('\r\n');
const ical = new IcalEvent(ev, options);
return ical.toString();
}

@@ -596,3 +631,3 @@ /**

* Generates an RFC 2445 iCalendar stream from an array of events
* @param {NodeJS.WritableStream} stream
* @param {NodeJS.ReadableStream} stream
* @param {Event[]} events

@@ -610,8 +645,8 @@ * @param {HebrewCalendar.Options} options

['BEGIN:VCALENDAR', 'VERSION:2.0', `PRODID:-//hebcal.com/NONSGML Hebcal Calendar v1${version}//${uclang}`, 'CALSCALE:GREGORIAN', 'METHOD:PUBLISH', 'X-LOTUS-CHARSET:UTF-8', 'X-PUBLISHED-TTL:PT7D', `X-WR-CALNAME:${title}`, `X-WR-CALDESC:${caldesc}`].forEach(line => {
stream.write(line);
stream.write('\r\n');
stream.push(line);
stream.push('\r\n');
});
if (options.relcalid) {
stream.write(`X-WR-RELCALID:${options.relcalid}\r\n`);
stream.push(`X-WR-RELCALID:${options.relcalid}\r\n`);
}

@@ -623,7 +658,7 @@

const tzid = location.tzid;
stream.write(`X-WR-TIMEZONE;VALUE=TEXT:${tzid}\r\n`);
stream.push(`X-WR-TIMEZONE;VALUE=TEXT:${tzid}\r\n`);
if (VTIMEZONE[tzid]) {
stream.write(VTIMEZONE[tzid]);
stream.write('\r\n');
stream.push(VTIMEZONE[tzid]);
stream.push('\r\n');
} else {

@@ -635,4 +670,4 @@ try {

const str = lines.slice(3, lines.length - 2).join('\r\n');
stream.write(str);
stream.write('\r\n');
stream.push(str);
stream.push('\r\n');
VTIMEZONE[tzid] = str; // cache for later

@@ -646,12 +681,28 @@ } catch (error) {// ignore failure when no timezone definition to read

events.forEach(ev => {
const lines = eventToIcal1(ev, options);
const ical = new IcalEvent(ev, options);
const lines = ical.getFoldedLines();
lines.forEach(line => {
stream.write(line);
stream.write('\r\n');
stream.push(line);
stream.push('\r\n');
});
});
stream.write('END:VCALENDAR\r\n');
stream.end();
stream.push('END:VCALENDAR\r\n');
stream.push(null);
}
/**
* @private
* @param {stream.Readable} readable
* @return {string}
*/
async function readableToString(readable) {
let result = '';
for await (const chunk of readable) {
result += chunk;
}
return result;
}
/**
* Renders an array of events as a full RFC 2445 iCalendar string

@@ -663,17 +714,15 @@ * @param {Event[]} events

async function eventsToIcalendar(events, options) {
const writable = new stream.Writable();
const chunks = [];
writable._write = function (chunk, encoding, next) {
chunks.push(chunk);
next();
};
eventsToIcalendarStream(writable, events, options);
return Buffer.concat(chunks).toString('utf8');
const readStream = new stream.Readable();
eventsToIcalendarStream(readStream, events, options);
readStream.on('error', err => {
throw err;
});
return readableToString(readStream);
}
exports.IcalEvent = IcalEvent;
exports.eventToIcal = eventToIcal;
exports.eventsToIcalendar = eventsToIcalendar;
exports.eventsToIcalendarStream = eventsToIcalendarStream;
{
"name": "@hebcal/icalendar",
"version": "3.1.1",
"version": "3.2.0",
"author": "Michael J. Radwin (https://github.com/mjradwin)",

@@ -59,3 +59,3 @@ "keywords": [

"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/register": "^7.12.10",

@@ -62,0 +62,0 @@ "@rollup/plugin-babel": "^5.2.2",

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc