@hebcal/icalendar 6.3.7 → 6.3.8

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.
@@ -0,0 +1 @@
1
+ export declare function foldLine(line: string): string;
@@ -0,0 +1,51 @@
1
+ /*! @hebcal/icalendar v6.3.8 */
2
+ import { Buffer } from 'node:buffer';
3
+
4
+ let foldSegmenter;
5
+ const char74re = /.{1,74}/g;
6
+ function foldLine(line) {
7
+ const lineBytes = Buffer.byteLength(line);
8
+ if (lineBytes <= 74) {
9
+ return line;
10
+ }
11
+ if (lineBytes === line.length) {
12
+ // All-ASCII fast path: every UTF-16 unit encodes to one UTF-8 byte
13
+ // iff the string is pure ASCII, so we can split by JS chars.
14
+ return line.match(char74re).join('\r\n ');
15
+ }
16
+ // Walk grapheme clusters so we never split a multi-octet UTF-8
17
+ // sequence (or a combining/ZWJ/regional-indicator cluster) across
18
+ // a fold boundary. Reuse a single Segmenter to avoid per-call
19
+ // construction cost.
20
+ if (!foldSegmenter) {
21
+ foldSegmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
22
+ }
23
+ const parts = [];
24
+ let chunkStart = 0;
25
+ let len = 0;
26
+ for (const { segment, index } of foldSegmenter.segment(line)) {
27
+ const cp = segment.codePointAt(0);
28
+ // Most segments are a single code point; compute UTF-8 length
29
+ // arithmetically and skip the Buffer.byteLength call.
30
+ const cpUnits = cp >= 0x10000 ? 2 : 1;
31
+ let octets;
32
+ if (segment.length === cpUnits) {
33
+ octets = cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4;
34
+ }
35
+ else {
36
+ octets = Buffer.byteLength(segment);
37
+ }
38
+ if (len + octets >= 75) {
39
+ parts.push(line.slice(chunkStart, index));
40
+ chunkStart = index;
41
+ len = octets;
42
+ }
43
+ else {
44
+ len += octets;
45
+ }
46
+ }
47
+ parts.push(line.slice(chunkStart));
48
+ return parts.join('\r\n ');
49
+ }
50
+
51
+ export { foldLine };
package/dist/icalendar.js CHANGED
@@ -1,5 +1,4 @@
1
- /*! @hebcal/icalendar v6.3.7 */
2
- import { Buffer } from 'node:buffer';
1
+ /*! @hebcal/icalendar v6.3.8 */
3
2
  import { flags } from '@hebcal/core/dist/esm/event';
4
3
  import { Locale } from '@hebcal/core/dist/esm/locale';
5
4
  import { murmur32HexSync } from 'murmurhash3';
@@ -11,6 +10,7 @@ import { appendIsraelAndTracking } from '@hebcal/rest-api/dist/esm/url';
11
10
  import { makeAnchor } from '@hebcal/rest-api/dist/esm/makeAnchor';
12
11
  import { promises } from 'node:fs';
13
12
  import { version } from './pkgVersion.js';
13
+ import { foldLine } from './foldLine.js';
14
14
 
15
15
  const vtimezoneCache = new Map();
16
16
  const CATEGORY = {
@@ -57,7 +57,6 @@ function appendTrackingToUrl(url, options) {
57
57
  const utmCampaign = options.utmCampaign;
58
58
  return appendIsraelAndTracking(url, options.il, utmSource, utmMedium, utmCampaign);
59
59
  }
60
- const char74re = /(.{1,74})/g;
61
60
  const DAILY_LEARNING = flags.DAILY_LEARNING |
62
61
  flags.DAF_YOMI |
63
62
  flags.MISHNA_YOMI |
@@ -266,50 +265,13 @@ class IcalEvent {
266
265
  * fold lines to 75 characters
267
266
  */
268
267
  getLines() {
269
- return this.getLongLines().map(IcalEvent.fold);
268
+ return this.getLongLines().map(foldLine);
270
269
  }
271
270
  /**
272
271
  * fold line to 75 characters
273
272
  */
274
273
  static fold(line) {
275
- if (Buffer.byteLength(line) <= 74) {
276
- return line;
277
- }
278
- let isASCII = true;
279
- for (let i = 0; i < line.length; i++) {
280
- if (line.codePointAt(i) > 255) {
281
- isASCII = false;
282
- break;
283
- }
284
- }
285
- if (isASCII) {
286
- // It's longer than 74 octets, and all characters are ASCII, so we
287
- // use a simple regex to split it into chunks of 74 characters
288
- const matches = line.match(char74re);
289
- return matches.join('\r\n ');
290
- }
291
- // iterate unicode character by character, making sure
292
- // that adding a new character would keep the line <= 75 octets
293
- const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
294
- const segments = segmenter.segment(line);
295
- const chars = Array.from(segments, s => s.segment);
296
- let result = '';
297
- let current = '';
298
- let len = 0;
299
- for (const ch of chars) {
300
- const octets = ch.codePointAt(0) < 256 ? 1 : Buffer.byteLength(ch);
301
- const newlen = len + octets;
302
- if (newlen < 75) {
303
- current += ch;
304
- len = newlen;
305
- }
306
- else {
307
- result += current + '\r\n ';
308
- current = ch;
309
- len = octets;
310
- }
311
- }
312
- return result + current;
274
+ return foldLine(line);
313
275
  }
314
276
  static escape(str) {
315
277
  if (str.includes(',')) {
@@ -517,7 +479,7 @@ async function icalEventsToString(icals, options) {
517
479
  throw new TypeError('Invalid options object');
518
480
  const stream = [];
519
481
  const preamble = makeIcalPreamble(options);
520
- for (const line of preamble.map(IcalEvent.fold)) {
482
+ for (const line of preamble.map(foldLine)) {
521
483
  stream.push(line);
522
484
  stream.push('\r\n');
523
485
  }
@@ -1 +1 @@
1
- export declare const version = "6.3.7";
1
+ export declare const version = "6.3.8";
@@ -1,5 +1,5 @@
1
- /*! @hebcal/icalendar v6.3.7 */
1
+ /*! @hebcal/icalendar v6.3.8 */
2
2
  // DO NOT EDIT THIS AUTO-GENERATED FILE!
3
- const version = '6.3.7';
3
+ const version = '6.3.8';
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.7",
3
+ "version": "6.3.8",
4
4
  "author": "Michael J. Radwin (https://github.com/mjradwin)",
5
5
  "keywords": [
6
6
  "ical",
@@ -30,9 +30,9 @@
30
30
  },
31
31
  "homepage": "https://hebcal.github.io/api/icalendar/",
32
32
  "dependencies": {
33
- "@hebcal/core": "^6.1.0",
34
- "@hebcal/hdate": "^0.22.0",
35
- "@hebcal/rest-api": "^6.4.3",
33
+ "@hebcal/core": "^6.3.3",
34
+ "@hebcal/hdate": "^0.22.2",
35
+ "@hebcal/rest-api": "^6.4.7",
36
36
  "murmurhash3": "^0.5.0",
37
37
  "tslib": "^2.8.1"
38
38
  },
@@ -50,13 +50,13 @@
50
50
  },
51
51
  "license": "BSD-2-Clause",
52
52
  "devDependencies": {
53
- "@hebcal/learning": "^6.7.2",
53
+ "@hebcal/learning": "^6.8.0",
54
54
  "@rollup/plugin-typescript": "^12.3.0",
55
55
  "@types/node": "25.6.0",
56
56
  "gts": "^7.0.0",
57
- "rollup": "^4.60.1",
58
- "typedoc": "^0.28.18",
59
- "typescript": "^6.0.2",
60
- "vitest": "^4.1.4"
57
+ "rollup": "^4.60.2",
58
+ "typedoc": "^0.28.19",
59
+ "typescript": "^6.0.3",
60
+ "vitest": "^4.1.5"
61
61
  }
62
62
  }