@hebcal/icalendar 7.0.2 → 7.0.3
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/foldLine.js +63 -21
- package/dist/pkgVersion.d.ts +1 -1
- package/dist/pkgVersion.js +1 -1
- package/package.json +5 -5
package/dist/foldLine.js
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
2
|
let foldSegmenter;
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Number of UTF-8 octets used to encode the code point starting at `i`.
|
|
5
|
+
* Returns 4 for a surrogate pair (which occupies two UTF-16 units).
|
|
6
|
+
*/
|
|
7
|
+
function octetsAt(line, i) {
|
|
8
|
+
const c = line.charCodeAt(i);
|
|
9
|
+
if (c < 0x80) {
|
|
10
|
+
return 1;
|
|
11
|
+
}
|
|
12
|
+
if (c < 0x800) {
|
|
13
|
+
return 2;
|
|
14
|
+
}
|
|
15
|
+
// A high surrogate starts a 4-octet code point; an unpaired surrogate
|
|
16
|
+
// still encodes as 3 octets, but WHATWG replaces it with U+FFFD, which
|
|
17
|
+
// is also 3 octets, so the count stays correct either way.
|
|
18
|
+
if (c >= 0xd800 && c <= 0xdbff && i + 1 < line.length) {
|
|
19
|
+
const lo = line.charCodeAt(i + 1);
|
|
20
|
+
if (lo >= 0xdc00 && lo <= 0xdfff) {
|
|
21
|
+
return 4;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return 3;
|
|
25
|
+
}
|
|
4
26
|
export function foldLine(line) {
|
|
5
27
|
const lineBytes = Buffer.byteLength(line);
|
|
6
28
|
if (lineBytes <= 74) {
|
|
@@ -9,38 +31,58 @@ export function foldLine(line) {
|
|
|
9
31
|
if (lineBytes === line.length) {
|
|
10
32
|
// All-ASCII fast path: every UTF-16 unit encodes to one UTF-8 byte
|
|
11
33
|
// iff the string is pure ASCII, so we can split by JS chars.
|
|
12
|
-
|
|
34
|
+
// A /.{1,74}/g regex looks tempting here but is wrong: `.` does not
|
|
35
|
+
// match \r or \n, so it silently drops those characters and returns
|
|
36
|
+
// null outright for a line built only from them.
|
|
37
|
+
const parts = [];
|
|
38
|
+
for (let i = 0; i < line.length; i += 74) {
|
|
39
|
+
parts.push(line.slice(i, i + 74));
|
|
40
|
+
}
|
|
41
|
+
return parts.join('\r\n ');
|
|
13
42
|
}
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
43
|
+
// Fold on code-point boundaries so a multi-octet UTF-8 sequence is never
|
|
44
|
+
// split, then pull each break back to the start of its grapheme cluster
|
|
45
|
+
// so combining marks, ZWJ sequences and regional-indicator pairs stay
|
|
46
|
+
// with their base character.
|
|
47
|
+
//
|
|
48
|
+
// Only the break positions need the Segmenter, and there are at most
|
|
49
|
+
// lineBytes/74 of them, so we ask it about those offsets via
|
|
50
|
+
// `containing()` rather than iterating every cluster in the line --
|
|
51
|
+
// the same fold points for a fraction of the work.
|
|
18
52
|
if (!foldSegmenter) {
|
|
19
53
|
foldSegmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
|
|
20
54
|
}
|
|
55
|
+
const segments = foldSegmenter.segment(line);
|
|
21
56
|
const parts = [];
|
|
57
|
+
const n = line.length;
|
|
22
58
|
let chunkStart = 0;
|
|
23
59
|
let len = 0;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const cpUnits = cp >= 0x10000 ? 2 : 1;
|
|
29
|
-
let octets;
|
|
30
|
-
if (segment.length === cpUnits) {
|
|
31
|
-
octets = cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4;
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
octets = Buffer.byteLength(segment);
|
|
35
|
-
}
|
|
60
|
+
let i = 0;
|
|
61
|
+
while (i < n) {
|
|
62
|
+
const octets = octetsAt(line, i);
|
|
63
|
+
const units = octets === 4 ? 2 : 1;
|
|
36
64
|
if (len + octets >= 75) {
|
|
37
|
-
|
|
38
|
-
chunkStart
|
|
39
|
-
|
|
65
|
+
let brk = i;
|
|
66
|
+
if (i > chunkStart) {
|
|
67
|
+
const cluster = segments.containing(i);
|
|
68
|
+
// Back up to the cluster start, unless that would consume the whole
|
|
69
|
+
// chunk -- a single cluster wider than the limit has to be split.
|
|
70
|
+
if (cluster && cluster.index > chunkStart && cluster.index < i) {
|
|
71
|
+
brk = cluster.index;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
parts.push(line.slice(chunkStart, brk));
|
|
75
|
+
chunkStart = brk;
|
|
76
|
+
// Anything we backed up over carries into the next chunk.
|
|
77
|
+
len = 0;
|
|
78
|
+
for (let k = brk; k < i + units; k += octetsAt(line, k) === 4 ? 2 : 1) {
|
|
79
|
+
len += octetsAt(line, k);
|
|
80
|
+
}
|
|
40
81
|
}
|
|
41
82
|
else {
|
|
42
83
|
len += octets;
|
|
43
84
|
}
|
|
85
|
+
i += units;
|
|
44
86
|
}
|
|
45
87
|
parts.push(line.slice(chunkStart));
|
|
46
88
|
return parts.join('\r\n ');
|
package/dist/pkgVersion.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "7.0.
|
|
1
|
+
export declare const version = "7.0.3";
|
package/dist/pkgVersion.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// DO NOT EDIT THIS AUTO-GENERATED FILE!
|
|
2
|
-
export const version = '7.0.
|
|
2
|
+
export const version = '7.0.3';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hebcal/icalendar",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.3",
|
|
4
4
|
"author": "Michael J. Radwin (https://github.com/mjradwin)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ical",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@hebcal/core": "^6.9.1",
|
|
34
34
|
"@hebcal/hdate": "^0.22.7",
|
|
35
35
|
"@hebcal/murmurhash3": "^1.0.0",
|
|
36
|
-
"@hebcal/rest-api": "^7.1.
|
|
36
|
+
"@hebcal/rest-api": "^7.1.3"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build:version": "node ./version.js package.json src/pkgVersion.ts",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
},
|
|
49
49
|
"license": "BSD-2-Clause",
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@hebcal/learning": "^6.9.
|
|
52
|
-
"@types/node": "26.
|
|
53
|
-
"oxlint": "^1.
|
|
51
|
+
"@hebcal/learning": "^6.9.7",
|
|
52
|
+
"@types/node": "26.2.0",
|
|
53
|
+
"oxlint": "^1.77.0",
|
|
54
54
|
"prettier": "^3.9.6",
|
|
55
55
|
"typescript": "^7.0.2",
|
|
56
56
|
"vitest": "^4.1.10"
|