@hebcal/icalendar 6.3.4 → 6.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,6 @@ export type ICalEventOptions = {
14
14
  publishedTTL?: string | boolean;
15
15
  calendarColor?: string;
16
16
  relcalid?: string;
17
- yahrzeit?: boolean;
18
17
  subscribe?: string | boolean;
19
18
  url?: boolean;
20
19
  };
package/dist/icalendar.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @hebcal/icalendar v6.3.4 */
1
+ /*! @hebcal/icalendar v6.3.6 */
2
2
  import { flags } from '@hebcal/core/dist/esm/event';
3
3
  import { Locale } from '@hebcal/core/dist/esm/locale';
4
4
  import { murmur32HexSync } from 'murmurhash3';
@@ -260,7 +260,7 @@ class IcalEvent {
260
260
  static fold(line) {
261
261
  let isASCII = true;
262
262
  for (let i = 0; i < line.length; i++) {
263
- if (line.charCodeAt(i) > 255) {
263
+ if (line.codePointAt(i) > 255) {
264
264
  isASCII = false;
265
265
  break;
266
266
  }
@@ -277,33 +277,33 @@ class IcalEvent {
277
277
  }
278
278
  // iterate unicode character by character, making sure
279
279
  // that adding a new character would keep the line <= 75 octets
280
+ const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
281
+ const segments = segmenter.segment(line);
282
+ const chars = Array.from(segments, s => s.segment);
280
283
  let result = '';
281
284
  let current = '';
282
285
  let len = 0;
283
- for (let i = 0; i < line.length; i++) {
284
- const char = line[i];
285
- const octets = char.charCodeAt(0) < 256 ? 1 : encoder.encode(char).length;
286
+ for (const ch of chars) {
287
+ const octets = ch.codePointAt(0) < 256 ? 1 : encoder.encode(ch).length;
286
288
  const newlen = len + octets;
287
289
  if (newlen < 75) {
288
- current += char;
290
+ current += ch;
289
291
  len = newlen;
290
292
  }
291
293
  else {
292
294
  result += current + '\r\n ';
293
- line = line.substring(i);
294
- current = '';
295
- len = 0;
296
- i = -1;
295
+ current = ch;
296
+ len = octets;
297
297
  }
298
298
  }
299
299
  return result + current;
300
300
  }
301
301
  static escape(str) {
302
302
  if (str.includes(',')) {
303
- str = str.replaceAll(',', '\\,');
303
+ str = str.replaceAll(',', String.raw `\,`);
304
304
  }
305
305
  if (str.includes(';')) {
306
- str = str.replaceAll(';', '\\;');
306
+ str = str.replaceAll(';', String.raw `\;`);
307
307
  }
308
308
  return str;
309
309
  }
@@ -441,26 +441,33 @@ const localeMap = {
441
441
  ashkenazi: 'en',
442
442
  ashkenazi_romanian: 'ro',
443
443
  };
444
- /**
445
- * Generates an RFC 2445 iCalendar string from an array of IcalEvents
446
- */
447
- async function icalEventsToString(icals, options) {
448
- if (!icals.length)
449
- throw new RangeError('Events can not be empty');
450
- if (!options)
451
- throw new TypeError('Invalid options object');
452
- const stream = [];
453
- const locale = options.locale || 'en';
444
+ async function getVtimezone(tzid) {
445
+ const vtz = vtimezoneCache.get(tzid);
446
+ if (typeof vtz === 'string') {
447
+ return vtz;
448
+ }
449
+ const filename = `./zoneinfo/${tzid}.ics`;
450
+ try {
451
+ const contents = await promises.readFile(filename, 'utf-8');
452
+ const lines = contents.split('\r\n');
453
+ // ignore first 3 and last 1 lines
454
+ const str = lines.slice(3, lines.length - 2).join('\r\n');
455
+ vtimezoneCache.set(tzid, str);
456
+ return str;
457
+ }
458
+ catch (_a) {
459
+ // ignore failure when no timezone definition to read
460
+ return undefined;
461
+ }
462
+ }
463
+ function makeIcalPreamble(opts) {
464
+ const locale = opts.locale || 'en';
454
465
  const lang = locale.length === 2 ? locale : localeMap[locale] || 'en';
455
466
  const uclang = lang.toUpperCase();
456
- const opts = Object.assign({}, options);
457
- opts.dtstamp = opts.dtstamp || IcalEvent.makeDtstamp(new Date());
458
467
  const title = opts.title ? IcalEvent.escape(opts.title) : 'Untitled';
459
468
  const caldesc = opts.caldesc
460
469
  ? IcalEvent.escape(opts.caldesc)
461
- : opts.yahrzeit
462
- ? 'Yahrzeits + Anniversaries from www.hebcal.com'
463
- : 'Jewish Holidays from www.hebcal.com';
470
+ : undefined;
464
471
  const prodid = opts.prodid ||
465
472
  `-//hebcal.com/NONSGML Hebcal Calendar v1${version}//${uclang}`;
466
473
  const preamble = [
@@ -473,46 +480,45 @@ async function icalEventsToString(icals, options) {
473
480
  ];
474
481
  if (opts.publishedTTL !== false) {
475
482
  const publishedTTL = opts.publishedTTL || 'P7D';
476
- preamble.push(`REFRESH-INTERVAL;VALUE=DURATION:${publishedTTL}`);
477
- preamble.push(`X-PUBLISHED-TTL:${publishedTTL}`);
483
+ preamble.push(`REFRESH-INTERVAL;VALUE=DURATION:${publishedTTL}`, `X-PUBLISHED-TTL:${publishedTTL}`);
478
484
  }
479
485
  preamble.push(`X-WR-CALNAME:${title}`);
480
- preamble.push(`X-WR-CALDESC:${caldesc}`);
486
+ if (caldesc) {
487
+ preamble.push(`X-WR-CALDESC:${caldesc}`);
488
+ }
489
+ const relcalid = opts.relcalid;
490
+ if (relcalid) {
491
+ preamble.push(`X-WR-RELCALID:${relcalid}`);
492
+ }
493
+ const calendarColor = opts.calendarColor;
494
+ if (calendarColor) {
495
+ preamble.push(`X-APPLE-CALENDAR-COLOR:${calendarColor}`);
496
+ }
497
+ return preamble;
498
+ }
499
+ /**
500
+ * Generates an RFC 2445 iCalendar string from an array of IcalEvents
501
+ */
502
+ async function icalEventsToString(icals, options) {
503
+ if (!icals.length)
504
+ throw new RangeError('Events can not be empty');
505
+ if (!options)
506
+ throw new TypeError('Invalid options object');
507
+ const stream = [];
508
+ const preamble = makeIcalPreamble(options);
481
509
  for (const line of preamble.map(IcalEvent.fold)) {
482
510
  stream.push(line);
483
511
  stream.push('\r\n');
484
512
  }
485
- if (opts.relcalid) {
486
- stream.push(IcalEvent.fold(`X-WR-RELCALID:${opts.relcalid}`));
487
- stream.push('\r\n');
488
- }
489
- if (opts.calendarColor) {
490
- stream.push(`X-APPLE-CALENDAR-COLOR:${opts.calendarColor}\r\n`);
491
- }
492
- const location = opts.location;
513
+ const location = options.location;
493
514
  const tzid = location === null || location === void 0 ? void 0 : location.getTzid();
494
515
  if (tzid) {
495
516
  stream.push(`X-WR-TIMEZONE;VALUE=TEXT:${tzid}\r\n`);
496
- const vtz = vtimezoneCache.get(tzid);
517
+ const vtz = await getVtimezone(tzid);
497
518
  if (typeof vtz === 'string') {
498
519
  stream.push(vtz);
499
520
  stream.push('\r\n');
500
521
  }
501
- else {
502
- const vtimezoneFilename = `./zoneinfo/${tzid}.ics`;
503
- try {
504
- const vtimezoneIcs = await promises.readFile(vtimezoneFilename, 'utf-8');
505
- const lines = vtimezoneIcs.split('\r\n');
506
- // ignore first 3 and last 1 lines
507
- const str = lines.slice(3, lines.length - 2).join('\r\n');
508
- stream.push(str);
509
- stream.push('\r\n');
510
- vtimezoneCache.set(tzid, str);
511
- }
512
- catch (_a) {
513
- // ignore failure when no timezone definition to read
514
- }
515
- }
516
522
  }
517
523
  for (const ical of icals) {
518
524
  const lines = ical.getLines();
@@ -1 +1 @@
1
- export declare const version = "6.3.4";
1
+ export declare const version = "6.3.6";
@@ -1,5 +1,5 @@
1
- /*! @hebcal/icalendar v6.3.4 */
1
+ /*! @hebcal/icalendar v6.3.6 */
2
2
  // DO NOT EDIT THIS AUTO-GENERATED FILE!
3
- const version = '6.3.4';
3
+ const version = '6.3.6';
4
4
 
5
5
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hebcal/icalendar",
3
- "version": "6.3.4",
3
+ "version": "6.3.6",
4
4
  "author": "Michael J. Radwin (https://github.com/mjradwin)",
5
5
  "keywords": [
6
6
  "ical",
@@ -50,13 +50,13 @@
50
50
  },
51
51
  "license": "BSD-2-Clause",
52
52
  "devDependencies": {
53
- "@hebcal/learning": "^6.6.0",
53
+ "@hebcal/learning": "^6.6.1",
54
54
  "@rollup/plugin-typescript": "^12.3.0",
55
- "@types/node": "25.0.6",
55
+ "@types/node": "25.3.0",
56
56
  "gts": "^7.0.0",
57
- "rollup": "^4.55.1",
58
- "typedoc": "^0.28.15",
57
+ "rollup": "^4.59.0",
58
+ "typedoc": "^0.28.17",
59
59
  "typescript": "^5.9.3",
60
- "vitest": "^4.0.16"
60
+ "vitest": "^4.0.18"
61
61
  }
62
62
  }