@hebcal/icalendar 6.3.4 → 6.3.5
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.
- package/dist/icalendar.js +57 -52
- package/dist/pkgVersion.d.ts +1 -1
- package/dist/pkgVersion.js +2 -2
- package/package.json +6 -6
package/dist/icalendar.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @hebcal/icalendar v6.3.
|
|
1
|
+
/*! @hebcal/icalendar v6.3.5 */
|
|
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.
|
|
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 (
|
|
284
|
-
const
|
|
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 +=
|
|
290
|
+
current += ch;
|
|
289
291
|
len = newlen;
|
|
290
292
|
}
|
|
291
293
|
else {
|
|
292
294
|
result += current + '\r\n ';
|
|
293
|
-
|
|
294
|
-
|
|
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,20 +441,29 @@ const localeMap = {
|
|
|
441
441
|
ashkenazi: 'en',
|
|
442
442
|
ashkenazi_romanian: 'ro',
|
|
443
443
|
};
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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)
|
|
@@ -473,46 +482,42 @@ async function icalEventsToString(icals, options) {
|
|
|
473
482
|
];
|
|
474
483
|
if (opts.publishedTTL !== false) {
|
|
475
484
|
const publishedTTL = opts.publishedTTL || 'P7D';
|
|
476
|
-
preamble.push(`REFRESH-INTERVAL;VALUE=DURATION:${publishedTTL}`);
|
|
477
|
-
|
|
485
|
+
preamble.push(`REFRESH-INTERVAL;VALUE=DURATION:${publishedTTL}`, `X-PUBLISHED-TTL:${publishedTTL}`);
|
|
486
|
+
}
|
|
487
|
+
preamble.push(`X-WR-CALNAME:${title}`, `X-WR-CALDESC:${caldesc}`);
|
|
488
|
+
const relcalid = opts.relcalid;
|
|
489
|
+
if (relcalid) {
|
|
490
|
+
preamble.push(`X-WR-RELCALID:${relcalid}`);
|
|
478
491
|
}
|
|
479
|
-
|
|
480
|
-
|
|
492
|
+
const calendarColor = opts.calendarColor;
|
|
493
|
+
if (calendarColor) {
|
|
494
|
+
preamble.push(`X-APPLE-CALENDAR-COLOR:${calendarColor}`);
|
|
495
|
+
}
|
|
496
|
+
return preamble;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Generates an RFC 2445 iCalendar string from an array of IcalEvents
|
|
500
|
+
*/
|
|
501
|
+
async function icalEventsToString(icals, options) {
|
|
502
|
+
if (!icals.length)
|
|
503
|
+
throw new RangeError('Events can not be empty');
|
|
504
|
+
if (!options)
|
|
505
|
+
throw new TypeError('Invalid options object');
|
|
506
|
+
const stream = [];
|
|
507
|
+
const preamble = makeIcalPreamble(options);
|
|
481
508
|
for (const line of preamble.map(IcalEvent.fold)) {
|
|
482
509
|
stream.push(line);
|
|
483
510
|
stream.push('\r\n');
|
|
484
511
|
}
|
|
485
|
-
|
|
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;
|
|
512
|
+
const location = options.location;
|
|
493
513
|
const tzid = location === null || location === void 0 ? void 0 : location.getTzid();
|
|
494
514
|
if (tzid) {
|
|
495
515
|
stream.push(`X-WR-TIMEZONE;VALUE=TEXT:${tzid}\r\n`);
|
|
496
|
-
const vtz =
|
|
516
|
+
const vtz = await getVtimezone(tzid);
|
|
497
517
|
if (typeof vtz === 'string') {
|
|
498
518
|
stream.push(vtz);
|
|
499
519
|
stream.push('\r\n');
|
|
500
520
|
}
|
|
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
521
|
}
|
|
517
522
|
for (const ical of icals) {
|
|
518
523
|
const lines = ical.getLines();
|
package/dist/pkgVersion.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "6.3.
|
|
1
|
+
export declare const version = "6.3.5";
|
package/dist/pkgVersion.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hebcal/icalendar",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.5",
|
|
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.
|
|
53
|
+
"@hebcal/learning": "^6.6.1",
|
|
54
54
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
55
|
-
"@types/node": "25.0.
|
|
55
|
+
"@types/node": "25.0.10",
|
|
56
56
|
"gts": "^7.0.0",
|
|
57
|
-
"rollup": "^4.
|
|
58
|
-
"typedoc": "^0.28.
|
|
57
|
+
"rollup": "^4.56.0",
|
|
58
|
+
"typedoc": "^0.28.16",
|
|
59
59
|
"typescript": "^5.9.3",
|
|
60
|
-
"vitest": "^4.0.
|
|
60
|
+
"vitest": "^4.0.18"
|
|
61
61
|
}
|
|
62
62
|
}
|