@pipobscure/ical 0.0.1
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/LICENSE +190 -0
- package/README.md +661 -0
- package/dist/alarm.d.ts +35 -0
- package/dist/alarm.d.ts.map +1 -0
- package/dist/alarm.js +87 -0
- package/dist/alarm.js.map +1 -0
- package/dist/calendar.d.ts +52 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +121 -0
- package/dist/calendar.js.map +1 -0
- package/dist/component.d.ts +48 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/component.js +170 -0
- package/dist/component.js.map +1 -0
- package/dist/event.d.ts +74 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +263 -0
- package/dist/event.js.map +1 -0
- package/dist/freebusy.d.ts +45 -0
- package/dist/freebusy.d.ts.map +1 -0
- package/dist/freebusy.js +111 -0
- package/dist/freebusy.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/journal.d.ts +48 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +148 -0
- package/dist/journal.js.map +1 -0
- package/dist/parse.d.ts +27 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +140 -0
- package/dist/parse.js.map +1 -0
- package/dist/property-registry.d.ts +31 -0
- package/dist/property-registry.d.ts.map +1 -0
- package/dist/property-registry.js +83 -0
- package/dist/property-registry.js.map +1 -0
- package/dist/property.d.ts +36 -0
- package/dist/property.d.ts.map +1 -0
- package/dist/property.js +135 -0
- package/dist/property.js.map +1 -0
- package/dist/timezone.d.ts +55 -0
- package/dist/timezone.d.ts.map +1 -0
- package/dist/timezone.js +141 -0
- package/dist/timezone.js.map +1 -0
- package/dist/todo.d.ts +67 -0
- package/dist/todo.d.ts.map +1 -0
- package/dist/todo.js +220 -0
- package/dist/todo.js.map +1 -0
- package/dist/tokenize.d.ts +22 -0
- package/dist/tokenize.d.ts.map +1 -0
- package/dist/tokenize.js +95 -0
- package/dist/tokenize.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/value-types.d.ts +81 -0
- package/dist/value-types.d.ts.map +1 -0
- package/dist/value-types.js +445 -0
- package/dist/value-types.js.map +1 -0
- package/package.json +45 -0
- package/src/alarm.ts +105 -0
- package/src/calendar.ts +153 -0
- package/src/component.ts +193 -0
- package/src/event.ts +307 -0
- package/src/freebusy.ts +133 -0
- package/src/index.ts +85 -0
- package/src/journal.ts +174 -0
- package/src/parse.ts +166 -0
- package/src/property-registry.ts +124 -0
- package/src/property.ts +163 -0
- package/src/timezone.ts +169 -0
- package/src/todo.ts +253 -0
- package/src/tokenize.ts +99 -0
- package/src/types.ts +135 -0
- package/src/value-types.ts +498 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/** All structured value types produced by the parser and consumed by the serializer. */
|
|
2
|
+
export interface ICalDate {
|
|
3
|
+
readonly type: 'date';
|
|
4
|
+
readonly year: number;
|
|
5
|
+
readonly month: number;
|
|
6
|
+
readonly day: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ICalDateTime {
|
|
9
|
+
readonly type: 'date-time';
|
|
10
|
+
readonly year: number;
|
|
11
|
+
readonly month: number;
|
|
12
|
+
readonly day: number;
|
|
13
|
+
readonly hour: number;
|
|
14
|
+
readonly minute: number;
|
|
15
|
+
readonly second: number;
|
|
16
|
+
/** true when value ends with 'Z' (UTC) */
|
|
17
|
+
readonly utc: boolean;
|
|
18
|
+
/** TZID parameter value when present */
|
|
19
|
+
readonly tzid?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ICalTime {
|
|
22
|
+
readonly type: 'time';
|
|
23
|
+
readonly hour: number;
|
|
24
|
+
readonly minute: number;
|
|
25
|
+
readonly second: number;
|
|
26
|
+
readonly utc: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface ICalDuration {
|
|
29
|
+
readonly type: 'duration';
|
|
30
|
+
readonly negative: boolean;
|
|
31
|
+
readonly weeks?: number;
|
|
32
|
+
readonly days?: number;
|
|
33
|
+
readonly hours?: number;
|
|
34
|
+
readonly minutes?: number;
|
|
35
|
+
readonly seconds?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ICalPeriod {
|
|
38
|
+
readonly type: 'period';
|
|
39
|
+
readonly start: ICalDateTime;
|
|
40
|
+
readonly end: ICalDateTime | ICalDuration;
|
|
41
|
+
}
|
|
42
|
+
export type RecurFreq = 'SECONDLY' | 'MINUTELY' | 'HOURLY' | 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'YEARLY';
|
|
43
|
+
export type Weekday = 'SU' | 'MO' | 'TU' | 'WE' | 'TH' | 'FR' | 'SA';
|
|
44
|
+
export interface ByDayRule {
|
|
45
|
+
readonly day: Weekday;
|
|
46
|
+
/** ordinal week number, e.g. +1 = first, -1 = last */
|
|
47
|
+
readonly ordwk?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface ICalRecur {
|
|
50
|
+
readonly type: 'recur';
|
|
51
|
+
readonly freq: RecurFreq;
|
|
52
|
+
readonly until?: ICalDate | ICalDateTime;
|
|
53
|
+
readonly count?: number;
|
|
54
|
+
readonly interval?: number;
|
|
55
|
+
readonly bysecond?: readonly number[];
|
|
56
|
+
readonly byminute?: readonly number[];
|
|
57
|
+
readonly byhour?: readonly number[];
|
|
58
|
+
readonly byday?: readonly ByDayRule[];
|
|
59
|
+
readonly bymonthday?: readonly number[];
|
|
60
|
+
readonly byyearday?: readonly number[];
|
|
61
|
+
readonly byweekno?: readonly number[];
|
|
62
|
+
readonly bymonth?: readonly number[];
|
|
63
|
+
readonly bysetpos?: readonly number[];
|
|
64
|
+
readonly wkst?: Weekday;
|
|
65
|
+
}
|
|
66
|
+
export interface ICalUtcOffset {
|
|
67
|
+
readonly type: 'utc-offset';
|
|
68
|
+
readonly sign: '+' | '-';
|
|
69
|
+
readonly hours: number;
|
|
70
|
+
readonly minutes: number;
|
|
71
|
+
readonly seconds?: number;
|
|
72
|
+
}
|
|
73
|
+
export interface ICalGeo {
|
|
74
|
+
readonly type: 'geo';
|
|
75
|
+
readonly latitude: number;
|
|
76
|
+
readonly longitude: number;
|
|
77
|
+
}
|
|
78
|
+
/** BINARY value — base64-encoded data wrapped in a tagged type for discriminated union safety */
|
|
79
|
+
export interface ICalBinary {
|
|
80
|
+
readonly type: 'binary';
|
|
81
|
+
readonly data: Uint8Array;
|
|
82
|
+
}
|
|
83
|
+
/** Union of all structured iCal values — every member has a `type` discriminant */
|
|
84
|
+
export type ICalStructured = ICalDate | ICalDateTime | ICalTime | ICalDuration | ICalPeriod | ICalRecur | ICalUtcOffset | ICalGeo | ICalBinary;
|
|
85
|
+
/** Full iCal value union (scalars + structured) */
|
|
86
|
+
export type ICalValue = string | number | boolean | ICalStructured;
|
|
87
|
+
/** A parsed content line before value interpretation */
|
|
88
|
+
export interface ContentLine {
|
|
89
|
+
readonly name: string;
|
|
90
|
+
readonly params: Readonly<Record<string, string | readonly string[]>>;
|
|
91
|
+
readonly value: string;
|
|
92
|
+
}
|
|
93
|
+
/** A fully parsed property with typed value */
|
|
94
|
+
export interface ParsedProperty {
|
|
95
|
+
readonly name: string;
|
|
96
|
+
readonly params: Readonly<Record<string, string | readonly string[]>>;
|
|
97
|
+
readonly value: ICalValue | readonly ICalValue[];
|
|
98
|
+
readonly rawValue: string;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wFAAwF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 5545 §3.3 — Value Data Types
|
|
3
|
+
*
|
|
4
|
+
* Each exported object has:
|
|
5
|
+
* parse(raw, params?) → typed value (tolerant)
|
|
6
|
+
* serialize(val, params?) → string (strict)
|
|
7
|
+
*/
|
|
8
|
+
import type { ICalDate, ICalDateTime, ICalTime, ICalDuration, ICalPeriod, ICalRecur, ICalUtcOffset, ICalGeo, ICalBinary } from './types.js';
|
|
9
|
+
declare function isValidDate(y: number, m: number, d: number): boolean;
|
|
10
|
+
export declare const TEXT: {
|
|
11
|
+
parse(raw: string): string;
|
|
12
|
+
serialize(val: unknown): string;
|
|
13
|
+
};
|
|
14
|
+
export declare const BOOLEAN: {
|
|
15
|
+
parse(raw: string): boolean;
|
|
16
|
+
serialize(val: unknown): string;
|
|
17
|
+
};
|
|
18
|
+
export declare const INTEGER: {
|
|
19
|
+
parse(raw: string): number;
|
|
20
|
+
serialize(val: unknown): string;
|
|
21
|
+
};
|
|
22
|
+
export declare const FLOAT: {
|
|
23
|
+
parse(raw: string): number;
|
|
24
|
+
serialize(val: unknown): string;
|
|
25
|
+
};
|
|
26
|
+
export declare const URI: {
|
|
27
|
+
parse(raw: string): string;
|
|
28
|
+
serialize(val: unknown): string;
|
|
29
|
+
};
|
|
30
|
+
export declare const CAL_ADDRESS: {
|
|
31
|
+
parse(raw: string): string;
|
|
32
|
+
serialize(val: unknown): string;
|
|
33
|
+
};
|
|
34
|
+
export declare const BINARY: {
|
|
35
|
+
parse(raw: string): ICalBinary;
|
|
36
|
+
serialize(val: unknown): string;
|
|
37
|
+
};
|
|
38
|
+
export declare const UTC_OFFSET: {
|
|
39
|
+
parse(raw: string): ICalUtcOffset;
|
|
40
|
+
serialize(val: ICalUtcOffset): string;
|
|
41
|
+
};
|
|
42
|
+
export declare const DATE: {
|
|
43
|
+
parse(raw: string): ICalDate;
|
|
44
|
+
serialize(val: ICalDate | Date): string;
|
|
45
|
+
fromDate(d: Date): ICalDate;
|
|
46
|
+
toDate(val: ICalDate): Date;
|
|
47
|
+
};
|
|
48
|
+
export declare const DATE_TIME: {
|
|
49
|
+
parse(raw: string, params?: Readonly<Record<string, unknown>>): ICalDateTime;
|
|
50
|
+
serialize(val: ICalDateTime | Date, tzid?: string): string;
|
|
51
|
+
fromDate(d: Date, tzid?: string): ICalDateTime;
|
|
52
|
+
toDate(val: ICalDateTime): Date;
|
|
53
|
+
};
|
|
54
|
+
export declare const TIME: {
|
|
55
|
+
parse(raw: string): ICalTime;
|
|
56
|
+
serialize(val: ICalTime): string;
|
|
57
|
+
};
|
|
58
|
+
export declare const DURATION: {
|
|
59
|
+
parse(raw: string): ICalDuration;
|
|
60
|
+
serialize(val: ICalDuration): string;
|
|
61
|
+
toSeconds(val: ICalDuration): number;
|
|
62
|
+
};
|
|
63
|
+
export declare const PERIOD: {
|
|
64
|
+
parse(raw: string): ICalPeriod;
|
|
65
|
+
serialize(val: ICalPeriod): string;
|
|
66
|
+
};
|
|
67
|
+
export declare const RECUR: {
|
|
68
|
+
parse(raw: string): ICalRecur;
|
|
69
|
+
serialize(val: ICalRecur): string;
|
|
70
|
+
};
|
|
71
|
+
export declare const GEO: {
|
|
72
|
+
parse(raw: string): ICalGeo;
|
|
73
|
+
serialize(val: ICalGeo): string;
|
|
74
|
+
};
|
|
75
|
+
type Codec = {
|
|
76
|
+
parse(raw: string, params?: Readonly<Record<string, unknown>>): unknown;
|
|
77
|
+
serialize(val: unknown): string;
|
|
78
|
+
};
|
|
79
|
+
export declare const CODECS: Readonly<Record<string, Codec>>;
|
|
80
|
+
export { isValidDate };
|
|
81
|
+
//# sourceMappingURL=value-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value-types.d.ts","sourceRoot":"","sources":["../src/value-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,SAAS,EACT,aAAa,EACb,OAAO,EACP,UAAU,EAIX,MAAM,YAAY,CAAC;AAYpB,iBAAS,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAI7D;AAID,eAAO,MAAM,IAAI;eACJ,MAAM,GAAG,MAAM;mBAQX,OAAO,GAAG,MAAM;CAQhC,CAAC;AAIF,eAAO,MAAM,OAAO;eACP,MAAM,GAAG,OAAO;mBAGZ,OAAO,GAAG,MAAM;CAGhC,CAAC;AAIF,eAAO,MAAM,OAAO;eACP,MAAM,GAAG,MAAM;mBAGX,OAAO,GAAG,MAAM;CAGhC,CAAC;AAIF,eAAO,MAAM,KAAK;eACL,MAAM,GAAG,MAAM;mBAGX,OAAO,GAAG,MAAM;CAIhC,CAAC;AAIF,eAAO,MAAM,GAAG;eACH,MAAM,GAAG,MAAM;mBAGX,OAAO,GAAG,MAAM;CAGhC,CAAC;AAEF,eAAO,MAAM,WAAW;eARX,MAAM,GAAG,MAAM;mBAGX,OAAO,GAAG,MAAM;CAKH,CAAC;AAI/B,eAAO,MAAM,MAAM;eACN,MAAM,GAAG,UAAU;mBAIf,OAAO,GAAG,MAAM;CAQhC,CAAC;AAIF,eAAO,MAAM,UAAU;eACV,MAAM,GAAG,aAAa;mBAQlB,aAAa,GAAG,MAAM;CAKtC,CAAC;AAIF,eAAO,MAAM,IAAI;eACJ,MAAM,GAAG,QAAQ;mBASb,QAAQ,GAAG,IAAI,GAAG,MAAM;gBAM3B,IAAI,GAAG,QAAQ;gBAQf,QAAQ,GAAG,IAAI;CAG5B,CAAC;AAIF,eAAO,MAAM,SAAS;eACT,MAAM,WAAW,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,YAAY;mBAiB7D,YAAY,GAAG,IAAI,SAAS,MAAM,GAAG,MAAM;gBAY9C,IAAI,SAAS,MAAM,GAAG,YAAY;gBAyBlC,YAAY,GAAG,IAAI;CAQhC,CAAC;AAIF,eAAO,MAAM,IAAI;eACJ,MAAM,GAAG,QAAQ;mBAYb,QAAQ,GAAG,MAAM;CAGjC,CAAC;AAaF,eAAO,MAAM,QAAQ;eACR,MAAM,GAAG,YAAY;mBAqCjB,YAAY,GAAG,MAAM;mBAiBrB,YAAY,GAAG,MAAM;CAWrC,CAAC;AAOF,eAAO,MAAM,MAAM;eACN,MAAM,GAAG,UAAU;mBAUf,UAAU,GAAG,MAAM;CAQnC,CAAC;AAqBF,eAAO,MAAM,KAAK;eACL,MAAM,GAAG,SAAS;mBA6Cd,SAAS,GAAG,MAAM;CA0BlC,CAAC;AAKF,eAAO,MAAM,GAAG;eACH,MAAM,GAAG,OAAO;mBAQZ,OAAO,GAAG,MAAM;CAGhC,CAAC;AAIF,KAAK,KAAK,GAAG;IAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC;IAAC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAE1H,eAAO,MAAM,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAelD,CAAC;AAGF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 5545 §3.3 — Value Data Types
|
|
3
|
+
*
|
|
4
|
+
* Each exported object has:
|
|
5
|
+
* parse(raw, params?) → typed value (tolerant)
|
|
6
|
+
* serialize(val, params?) → string (strict)
|
|
7
|
+
*/
|
|
8
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
9
|
+
function pad2(n) {
|
|
10
|
+
return String(n).padStart(2, '0');
|
|
11
|
+
}
|
|
12
|
+
function pad4(n) {
|
|
13
|
+
return String(n).padStart(4, '0');
|
|
14
|
+
}
|
|
15
|
+
function isValidDate(y, m, d) {
|
|
16
|
+
if (m < 1 || m > 12 || d < 1 || d > 31)
|
|
17
|
+
return false;
|
|
18
|
+
const dt = new Date(Date.UTC(y, m - 1, d));
|
|
19
|
+
return dt.getUTCFullYear() === y && dt.getUTCMonth() === m - 1 && dt.getUTCDate() === d;
|
|
20
|
+
}
|
|
21
|
+
// ── TEXT (RFC 5545 §3.3.11) ───────────────────────────────────────────────
|
|
22
|
+
export const TEXT = {
|
|
23
|
+
parse(raw) {
|
|
24
|
+
// Unescape: \n \N \, \; \\ → newline , ; backslash
|
|
25
|
+
return raw
|
|
26
|
+
.replace(/\\n/gi, '\n')
|
|
27
|
+
.replace(/\\,/g, ',')
|
|
28
|
+
.replace(/\\;/g, ';')
|
|
29
|
+
.replace(/\\\\/g, '\\');
|
|
30
|
+
},
|
|
31
|
+
serialize(val) {
|
|
32
|
+
if (val === null || val === undefined)
|
|
33
|
+
return '';
|
|
34
|
+
return String(val)
|
|
35
|
+
.replace(/\\/g, '\\\\')
|
|
36
|
+
.replace(/;/g, '\\;')
|
|
37
|
+
.replace(/,/g, '\\,')
|
|
38
|
+
.replace(/\n/g, '\\n');
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
// ── BOOLEAN (RFC 5545 §3.3.2) ─────────────────────────────────────────────
|
|
42
|
+
export const BOOLEAN = {
|
|
43
|
+
parse(raw) {
|
|
44
|
+
return raw.trim().toUpperCase() === 'TRUE';
|
|
45
|
+
},
|
|
46
|
+
serialize(val) {
|
|
47
|
+
return val ? 'TRUE' : 'FALSE';
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
// ── INTEGER (RFC 5545 §3.3.8) ─────────────────────────────────────────────
|
|
51
|
+
export const INTEGER = {
|
|
52
|
+
parse(raw) {
|
|
53
|
+
return parseInt(raw.trim(), 10);
|
|
54
|
+
},
|
|
55
|
+
serialize(val) {
|
|
56
|
+
return String(Math.trunc(Number(val)));
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
// ── FLOAT (RFC 5545 §3.3.7) ───────────────────────────────────────────────
|
|
60
|
+
export const FLOAT = {
|
|
61
|
+
parse(raw) {
|
|
62
|
+
return parseFloat(raw.trim());
|
|
63
|
+
},
|
|
64
|
+
serialize(val) {
|
|
65
|
+
const n = Number(val);
|
|
66
|
+
return Number.isInteger(n) ? `${n}.0` : String(n);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
// ── URI / CAL-ADDRESS (RFC 5545 §3.3.13, §3.3.3) ─────────────────────────
|
|
70
|
+
export const URI = {
|
|
71
|
+
parse(raw) {
|
|
72
|
+
return raw.trim();
|
|
73
|
+
},
|
|
74
|
+
serialize(val) {
|
|
75
|
+
return String(val ?? '');
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
export const CAL_ADDRESS = URI;
|
|
79
|
+
// ── BINARY (RFC 5545 §3.3.1) ──────────────────────────────────────────────
|
|
80
|
+
export const BINARY = {
|
|
81
|
+
parse(raw) {
|
|
82
|
+
const data = Buffer.from(raw.trim(), 'base64');
|
|
83
|
+
return { type: 'binary', data };
|
|
84
|
+
},
|
|
85
|
+
serialize(val) {
|
|
86
|
+
if (typeof val === 'object' && val !== null && 'type' in val && val.type === 'binary') {
|
|
87
|
+
const bin = val;
|
|
88
|
+
return Buffer.from(bin.data).toString('base64');
|
|
89
|
+
}
|
|
90
|
+
if (val instanceof Uint8Array)
|
|
91
|
+
return Buffer.from(val).toString('base64');
|
|
92
|
+
return String(val);
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
// ── UTC-OFFSET (RFC 5545 §3.3.14) ────────────────────────────────────────
|
|
96
|
+
export const UTC_OFFSET = {
|
|
97
|
+
parse(raw) {
|
|
98
|
+
const s = raw.trim();
|
|
99
|
+
const sign = s[0] === '-' ? '-' : '+';
|
|
100
|
+
const h = parseInt(s.slice(1, 3), 10);
|
|
101
|
+
const m = parseInt(s.slice(3, 5), 10);
|
|
102
|
+
const sec = s.length >= 7 ? parseInt(s.slice(5, 7), 10) : undefined;
|
|
103
|
+
return { type: 'utc-offset', sign, hours: h, minutes: m, seconds: sec };
|
|
104
|
+
},
|
|
105
|
+
serialize(val) {
|
|
106
|
+
const { sign, hours, minutes, seconds } = val;
|
|
107
|
+
const base = `${sign}${pad2(hours)}${pad2(minutes)}`;
|
|
108
|
+
return seconds !== undefined ? base + pad2(seconds) : base;
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
// ── DATE (RFC 5545 §3.3.4) ────────────────────────────────────────────────
|
|
112
|
+
export const DATE = {
|
|
113
|
+
parse(raw) {
|
|
114
|
+
const s = raw.trim();
|
|
115
|
+
return {
|
|
116
|
+
type: 'date',
|
|
117
|
+
year: parseInt(s.slice(0, 4), 10),
|
|
118
|
+
month: parseInt(s.slice(4, 6), 10),
|
|
119
|
+
day: parseInt(s.slice(6, 8), 10),
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
serialize(val) {
|
|
123
|
+
if (val instanceof Date) {
|
|
124
|
+
return `${pad4(val.getFullYear())}${pad2(val.getMonth() + 1)}${pad2(val.getDate())}`;
|
|
125
|
+
}
|
|
126
|
+
return `${pad4(val.year)}${pad2(val.month)}${pad2(val.day)}`;
|
|
127
|
+
},
|
|
128
|
+
fromDate(d) {
|
|
129
|
+
return {
|
|
130
|
+
type: 'date',
|
|
131
|
+
year: d.getFullYear(),
|
|
132
|
+
month: d.getMonth() + 1,
|
|
133
|
+
day: d.getDate(),
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
toDate(val) {
|
|
137
|
+
return new Date(val.year, val.month - 1, val.day);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
// ── DATE-TIME (RFC 5545 §3.3.5) ───────────────────────────────────────────
|
|
141
|
+
export const DATE_TIME = {
|
|
142
|
+
parse(raw, params) {
|
|
143
|
+
const s = raw.trim();
|
|
144
|
+
const utc = s.endsWith('Z');
|
|
145
|
+
const core = utc ? s.slice(0, -1) : s;
|
|
146
|
+
const tzid = typeof params?.['TZID'] === 'string' ? params['TZID'] : undefined;
|
|
147
|
+
return {
|
|
148
|
+
type: 'date-time',
|
|
149
|
+
year: parseInt(core.slice(0, 4), 10),
|
|
150
|
+
month: parseInt(core.slice(4, 6), 10),
|
|
151
|
+
day: parseInt(core.slice(6, 8), 10),
|
|
152
|
+
hour: parseInt(core.slice(9, 11), 10),
|
|
153
|
+
minute: parseInt(core.slice(11, 13), 10),
|
|
154
|
+
second: parseInt(core.slice(13, 15), 10),
|
|
155
|
+
utc,
|
|
156
|
+
tzid,
|
|
157
|
+
};
|
|
158
|
+
},
|
|
159
|
+
serialize(val, tzid) {
|
|
160
|
+
if (val instanceof Date) {
|
|
161
|
+
return (`${pad4(val.getUTCFullYear())}${pad2(val.getUTCMonth() + 1)}${pad2(val.getUTCDate())}` +
|
|
162
|
+
`T${pad2(val.getUTCHours())}${pad2(val.getUTCMinutes())}${pad2(val.getUTCSeconds())}Z`);
|
|
163
|
+
}
|
|
164
|
+
const core = `${pad4(val.year)}${pad2(val.month)}${pad2(val.day)}` +
|
|
165
|
+
`T${pad2(val.hour)}${pad2(val.minute)}${pad2(val.second)}`;
|
|
166
|
+
return val.utc ? core + 'Z' : core;
|
|
167
|
+
},
|
|
168
|
+
fromDate(d, tzid) {
|
|
169
|
+
if (tzid) {
|
|
170
|
+
return {
|
|
171
|
+
type: 'date-time',
|
|
172
|
+
year: d.getFullYear(),
|
|
173
|
+
month: d.getMonth() + 1,
|
|
174
|
+
day: d.getDate(),
|
|
175
|
+
hour: d.getHours(),
|
|
176
|
+
minute: d.getMinutes(),
|
|
177
|
+
second: d.getSeconds(),
|
|
178
|
+
utc: false,
|
|
179
|
+
tzid,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
type: 'date-time',
|
|
184
|
+
year: d.getUTCFullYear(),
|
|
185
|
+
month: d.getUTCMonth() + 1,
|
|
186
|
+
day: d.getUTCDate(),
|
|
187
|
+
hour: d.getUTCHours(),
|
|
188
|
+
minute: d.getUTCMinutes(),
|
|
189
|
+
second: d.getUTCSeconds(),
|
|
190
|
+
utc: true,
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
toDate(val) {
|
|
194
|
+
if (val.utc) {
|
|
195
|
+
return new Date(Date.UTC(val.year, val.month - 1, val.day, val.hour, val.minute, val.second));
|
|
196
|
+
}
|
|
197
|
+
return new Date(val.year, val.month - 1, val.day, val.hour, val.minute, val.second);
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
// ── TIME (RFC 5545 §3.3.12) ───────────────────────────────────────────────
|
|
201
|
+
export const TIME = {
|
|
202
|
+
parse(raw) {
|
|
203
|
+
const s = raw.trim();
|
|
204
|
+
const utc = s.endsWith('Z');
|
|
205
|
+
const core = utc ? s.slice(0, -1) : s;
|
|
206
|
+
return {
|
|
207
|
+
type: 'time',
|
|
208
|
+
hour: parseInt(core.slice(0, 2), 10),
|
|
209
|
+
minute: parseInt(core.slice(2, 4), 10),
|
|
210
|
+
second: parseInt(core.slice(4, 6), 10),
|
|
211
|
+
utc,
|
|
212
|
+
};
|
|
213
|
+
},
|
|
214
|
+
serialize(val) {
|
|
215
|
+
return `${pad2(val.hour)}${pad2(val.minute)}${pad2(val.second)}${val.utc ? 'Z' : ''}`;
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
// ── DURATION (RFC 5545 §3.3.6) ────────────────────────────────────────────
|
|
219
|
+
//
|
|
220
|
+
// dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
|
|
221
|
+
// dur-date = dur-day [dur-time]
|
|
222
|
+
// dur-time = "T" (dur-hour / dur-minute / dur-second)
|
|
223
|
+
// dur-week = 1*DIGIT "W"
|
|
224
|
+
// dur-hour = 1*DIGIT "H" [dur-minute]
|
|
225
|
+
// dur-minute= 1*DIGIT "M" [dur-second]
|
|
226
|
+
// dur-second= 1*DIGIT "S"
|
|
227
|
+
// dur-day = 1*DIGIT "D"
|
|
228
|
+
export const DURATION = {
|
|
229
|
+
parse(raw) {
|
|
230
|
+
const s = raw.trim();
|
|
231
|
+
const negative = s.startsWith('-');
|
|
232
|
+
const str = s.replace(/^[+-]/, '');
|
|
233
|
+
// Strip leading 'P'
|
|
234
|
+
if (!str.startsWith('P')) {
|
|
235
|
+
return { type: 'duration', negative, days: 0 };
|
|
236
|
+
}
|
|
237
|
+
const body = str.slice(1);
|
|
238
|
+
const weekMatch = body.match(/^(\d+)W$/);
|
|
239
|
+
if (weekMatch) {
|
|
240
|
+
return { type: 'duration', negative, weeks: parseInt(weekMatch[1], 10) };
|
|
241
|
+
}
|
|
242
|
+
let days;
|
|
243
|
+
let hours;
|
|
244
|
+
let minutes;
|
|
245
|
+
let seconds;
|
|
246
|
+
const dayMatch = body.match(/(\d+)D/);
|
|
247
|
+
if (dayMatch)
|
|
248
|
+
days = parseInt(dayMatch[1], 10);
|
|
249
|
+
const tIdx = body.indexOf('T');
|
|
250
|
+
if (tIdx !== -1) {
|
|
251
|
+
const timePart = body.slice(tIdx + 1);
|
|
252
|
+
const hourMatch = timePart.match(/(\d+)H/);
|
|
253
|
+
const minMatch = timePart.match(/(\d+)M/);
|
|
254
|
+
const secMatch = timePart.match(/(\d+)S/);
|
|
255
|
+
if (hourMatch)
|
|
256
|
+
hours = parseInt(hourMatch[1], 10);
|
|
257
|
+
if (minMatch)
|
|
258
|
+
minutes = parseInt(minMatch[1], 10);
|
|
259
|
+
if (secMatch)
|
|
260
|
+
seconds = parseInt(secMatch[1], 10);
|
|
261
|
+
}
|
|
262
|
+
return { type: 'duration', negative, days, hours, minutes, seconds };
|
|
263
|
+
},
|
|
264
|
+
serialize(val) {
|
|
265
|
+
const sign = val.negative ? '-' : '';
|
|
266
|
+
if (val.weeks !== undefined)
|
|
267
|
+
return `${sign}P${val.weeks}W`;
|
|
268
|
+
let s = `${sign}P`;
|
|
269
|
+
if (val.days)
|
|
270
|
+
s += `${val.days}D`;
|
|
271
|
+
const hasTime = val.hours || val.minutes || val.seconds;
|
|
272
|
+
if (hasTime) {
|
|
273
|
+
s += 'T';
|
|
274
|
+
if (val.hours)
|
|
275
|
+
s += `${val.hours}H`;
|
|
276
|
+
if (val.minutes)
|
|
277
|
+
s += `${val.minutes}M`;
|
|
278
|
+
if (val.seconds)
|
|
279
|
+
s += `${val.seconds}S`;
|
|
280
|
+
}
|
|
281
|
+
return s || `${sign}P0D`;
|
|
282
|
+
},
|
|
283
|
+
toSeconds(val) {
|
|
284
|
+
const sign = val.negative ? -1 : 1;
|
|
285
|
+
return (sign *
|
|
286
|
+
((val.weeks ?? 0) * 7 * 86400 +
|
|
287
|
+
(val.days ?? 0) * 86400 +
|
|
288
|
+
(val.hours ?? 0) * 3600 +
|
|
289
|
+
(val.minutes ?? 0) * 60 +
|
|
290
|
+
(val.seconds ?? 0)));
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
// ── PERIOD (RFC 5545 §3.3.9) ──────────────────────────────────────────────
|
|
294
|
+
//
|
|
295
|
+
// period = date-time "/" date-time (explicit)
|
|
296
|
+
// / date-time "/" dur-value (start + duration)
|
|
297
|
+
export const PERIOD = {
|
|
298
|
+
parse(raw) {
|
|
299
|
+
const slashIdx = raw.indexOf('/');
|
|
300
|
+
if (slashIdx === -1)
|
|
301
|
+
throw new Error(`Invalid PERIOD value: ${raw}`);
|
|
302
|
+
const start = DATE_TIME.parse(raw.slice(0, slashIdx));
|
|
303
|
+
const endStr = raw.slice(slashIdx + 1).trim();
|
|
304
|
+
const end = endStr.startsWith('P') || endStr.startsWith('-P') || endStr.startsWith('+P')
|
|
305
|
+
? DURATION.parse(endStr)
|
|
306
|
+
: DATE_TIME.parse(endStr);
|
|
307
|
+
return { type: 'period', start, end };
|
|
308
|
+
},
|
|
309
|
+
serialize(val) {
|
|
310
|
+
const startStr = DATE_TIME.serialize(val.start);
|
|
311
|
+
const endStr = val.end.type === 'duration'
|
|
312
|
+
? DURATION.serialize(val.end)
|
|
313
|
+
: DATE_TIME.serialize(val.end);
|
|
314
|
+
return `${startStr}/${endStr}`;
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
// ── RECUR (RFC 5545 §3.3.10) ──────────────────────────────────────────────
|
|
318
|
+
const VALID_FREQS = new Set([
|
|
319
|
+
'SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY',
|
|
320
|
+
]);
|
|
321
|
+
const VALID_WEEKDAYS = new Set(['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']);
|
|
322
|
+
function parseByDay(raw) {
|
|
323
|
+
return raw.split(',').map((s) => {
|
|
324
|
+
const m = s.trim().match(/^([+-]?\d+)?(SU|MO|TU|WE|TH|FR|SA)$/i);
|
|
325
|
+
if (!m)
|
|
326
|
+
return { day: 'MO' };
|
|
327
|
+
return {
|
|
328
|
+
day: (m[2].toUpperCase()),
|
|
329
|
+
ordwk: m[1] !== undefined ? parseInt(m[1], 10) : undefined,
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
export const RECUR = {
|
|
334
|
+
parse(raw) {
|
|
335
|
+
const parts = raw.trim().split(';');
|
|
336
|
+
const map = {};
|
|
337
|
+
for (const part of parts) {
|
|
338
|
+
const eq = part.indexOf('=');
|
|
339
|
+
if (eq === -1)
|
|
340
|
+
continue;
|
|
341
|
+
map[part.slice(0, eq).toUpperCase()] = part.slice(eq + 1);
|
|
342
|
+
}
|
|
343
|
+
const freqStr = (map['FREQ'] ?? '').toUpperCase();
|
|
344
|
+
if (!VALID_FREQS.has(freqStr)) {
|
|
345
|
+
throw new Error(`Invalid FREQ in RRULE: ${freqStr}`);
|
|
346
|
+
}
|
|
347
|
+
const freq = freqStr;
|
|
348
|
+
const parseInts = (k) => map[k]?.split(',').map(Number);
|
|
349
|
+
const parseWkst = (k) => {
|
|
350
|
+
const v = map[k]?.toUpperCase();
|
|
351
|
+
return v && VALID_WEEKDAYS.has(v) ? v : undefined;
|
|
352
|
+
};
|
|
353
|
+
let until;
|
|
354
|
+
if (map['UNTIL']) {
|
|
355
|
+
const u = map['UNTIL'];
|
|
356
|
+
until = u.includes('T') ? DATE_TIME.parse(u) : DATE.parse(u);
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
type: 'recur',
|
|
360
|
+
freq,
|
|
361
|
+
until,
|
|
362
|
+
count: map['COUNT'] !== undefined ? parseInt(map['COUNT'], 10) : undefined,
|
|
363
|
+
interval: map['INTERVAL'] !== undefined ? parseInt(map['INTERVAL'], 10) : undefined,
|
|
364
|
+
bysecond: parseInts('BYSECOND'),
|
|
365
|
+
byminute: parseInts('BYMINUTE'),
|
|
366
|
+
byhour: parseInts('BYHOUR'),
|
|
367
|
+
byday: map['BYDAY'] ? parseByDay(map['BYDAY']) : undefined,
|
|
368
|
+
bymonthday: parseInts('BYMONTHDAY'),
|
|
369
|
+
byyearday: parseInts('BYYEARDAY'),
|
|
370
|
+
byweekno: parseInts('BYWEEKNO'),
|
|
371
|
+
bymonth: parseInts('BYMONTH'),
|
|
372
|
+
bysetpos: parseInts('BYSETPOS'),
|
|
373
|
+
wkst: parseWkst('WKST'),
|
|
374
|
+
};
|
|
375
|
+
},
|
|
376
|
+
serialize(val) {
|
|
377
|
+
const parts = [`FREQ=${val.freq}`];
|
|
378
|
+
if (val.until) {
|
|
379
|
+
const u = val.until;
|
|
380
|
+
parts.push(`UNTIL=${u.type === 'date' ? DATE.serialize(u) : DATE_TIME.serialize(u)}`);
|
|
381
|
+
}
|
|
382
|
+
if (val.count !== undefined)
|
|
383
|
+
parts.push(`COUNT=${val.count}`);
|
|
384
|
+
if (val.interval !== undefined)
|
|
385
|
+
parts.push(`INTERVAL=${val.interval}`);
|
|
386
|
+
if (val.bysecond?.length)
|
|
387
|
+
parts.push(`BYSECOND=${val.bysecond.join(',')}`);
|
|
388
|
+
if (val.byminute?.length)
|
|
389
|
+
parts.push(`BYMINUTE=${val.byminute.join(',')}`);
|
|
390
|
+
if (val.byhour?.length)
|
|
391
|
+
parts.push(`BYHOUR=${val.byhour.join(',')}`);
|
|
392
|
+
if (val.byday?.length) {
|
|
393
|
+
parts.push(`BYDAY=${val.byday
|
|
394
|
+
.map((d) => (d.ordwk !== undefined ? `${d.ordwk}${d.day}` : d.day))
|
|
395
|
+
.join(',')}`);
|
|
396
|
+
}
|
|
397
|
+
if (val.bymonthday?.length)
|
|
398
|
+
parts.push(`BYMONTHDAY=${val.bymonthday.join(',')}`);
|
|
399
|
+
if (val.byyearday?.length)
|
|
400
|
+
parts.push(`BYYEARDAY=${val.byyearday.join(',')}`);
|
|
401
|
+
if (val.byweekno?.length)
|
|
402
|
+
parts.push(`BYWEEKNO=${val.byweekno.join(',')}`);
|
|
403
|
+
if (val.bymonth?.length)
|
|
404
|
+
parts.push(`BYMONTH=${val.bymonth.join(',')}`);
|
|
405
|
+
if (val.bysetpos?.length)
|
|
406
|
+
parts.push(`BYSETPOS=${val.bysetpos.join(',')}`);
|
|
407
|
+
if (val.wkst)
|
|
408
|
+
parts.push(`WKST=${val.wkst}`);
|
|
409
|
+
return parts.join(';');
|
|
410
|
+
},
|
|
411
|
+
};
|
|
412
|
+
// ── GEO — special compound property value (RFC 5545 §3.8.1.6) ────────────
|
|
413
|
+
// Value format: float ";" float
|
|
414
|
+
export const GEO = {
|
|
415
|
+
parse(raw) {
|
|
416
|
+
const [lat, lon] = raw.split(';');
|
|
417
|
+
return {
|
|
418
|
+
type: 'geo',
|
|
419
|
+
latitude: parseFloat(lat ?? '0'),
|
|
420
|
+
longitude: parseFloat(lon ?? '0'),
|
|
421
|
+
};
|
|
422
|
+
},
|
|
423
|
+
serialize(val) {
|
|
424
|
+
return `${val.latitude};${val.longitude}`;
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
export const CODECS = {
|
|
428
|
+
'TEXT': TEXT,
|
|
429
|
+
'BOOLEAN': BOOLEAN,
|
|
430
|
+
'INTEGER': INTEGER,
|
|
431
|
+
'FLOAT': FLOAT,
|
|
432
|
+
'URI': URI,
|
|
433
|
+
'CAL-ADDRESS': CAL_ADDRESS,
|
|
434
|
+
'BINARY': BINARY,
|
|
435
|
+
'UTC-OFFSET': UTC_OFFSET,
|
|
436
|
+
'DATE': DATE,
|
|
437
|
+
'DATE-TIME': DATE_TIME,
|
|
438
|
+
'TIME': TIME,
|
|
439
|
+
'DURATION': DURATION,
|
|
440
|
+
'PERIOD': PERIOD,
|
|
441
|
+
'RECUR': RECUR,
|
|
442
|
+
};
|
|
443
|
+
// Re-export isValidDate for use in serializer validation
|
|
444
|
+
export { isValidDate };
|
|
445
|
+
//# sourceMappingURL=value-types.js.map
|