@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.
Files changed (78) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +661 -0
  3. package/dist/alarm.d.ts +35 -0
  4. package/dist/alarm.d.ts.map +1 -0
  5. package/dist/alarm.js +87 -0
  6. package/dist/alarm.js.map +1 -0
  7. package/dist/calendar.d.ts +52 -0
  8. package/dist/calendar.d.ts.map +1 -0
  9. package/dist/calendar.js +121 -0
  10. package/dist/calendar.js.map +1 -0
  11. package/dist/component.d.ts +48 -0
  12. package/dist/component.d.ts.map +1 -0
  13. package/dist/component.js +170 -0
  14. package/dist/component.js.map +1 -0
  15. package/dist/event.d.ts +74 -0
  16. package/dist/event.d.ts.map +1 -0
  17. package/dist/event.js +263 -0
  18. package/dist/event.js.map +1 -0
  19. package/dist/freebusy.d.ts +45 -0
  20. package/dist/freebusy.d.ts.map +1 -0
  21. package/dist/freebusy.js +111 -0
  22. package/dist/freebusy.js.map +1 -0
  23. package/dist/index.d.ts +41 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +43 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/journal.d.ts +48 -0
  28. package/dist/journal.d.ts.map +1 -0
  29. package/dist/journal.js +148 -0
  30. package/dist/journal.js.map +1 -0
  31. package/dist/parse.d.ts +27 -0
  32. package/dist/parse.d.ts.map +1 -0
  33. package/dist/parse.js +140 -0
  34. package/dist/parse.js.map +1 -0
  35. package/dist/property-registry.d.ts +31 -0
  36. package/dist/property-registry.d.ts.map +1 -0
  37. package/dist/property-registry.js +83 -0
  38. package/dist/property-registry.js.map +1 -0
  39. package/dist/property.d.ts +36 -0
  40. package/dist/property.d.ts.map +1 -0
  41. package/dist/property.js +135 -0
  42. package/dist/property.js.map +1 -0
  43. package/dist/timezone.d.ts +55 -0
  44. package/dist/timezone.d.ts.map +1 -0
  45. package/dist/timezone.js +141 -0
  46. package/dist/timezone.js.map +1 -0
  47. package/dist/todo.d.ts +67 -0
  48. package/dist/todo.d.ts.map +1 -0
  49. package/dist/todo.js +220 -0
  50. package/dist/todo.js.map +1 -0
  51. package/dist/tokenize.d.ts +22 -0
  52. package/dist/tokenize.d.ts.map +1 -0
  53. package/dist/tokenize.js +95 -0
  54. package/dist/tokenize.js.map +1 -0
  55. package/dist/types.d.ts +100 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +3 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/value-types.d.ts +81 -0
  60. package/dist/value-types.d.ts.map +1 -0
  61. package/dist/value-types.js +445 -0
  62. package/dist/value-types.js.map +1 -0
  63. package/package.json +45 -0
  64. package/src/alarm.ts +105 -0
  65. package/src/calendar.ts +153 -0
  66. package/src/component.ts +193 -0
  67. package/src/event.ts +307 -0
  68. package/src/freebusy.ts +133 -0
  69. package/src/index.ts +85 -0
  70. package/src/journal.ts +174 -0
  71. package/src/parse.ts +166 -0
  72. package/src/property-registry.ts +124 -0
  73. package/src/property.ts +163 -0
  74. package/src/timezone.ts +169 -0
  75. package/src/todo.ts +253 -0
  76. package/src/tokenize.ts +99 -0
  77. package/src/types.ts +135 -0
  78. package/src/value-types.ts +498 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * VJOURNAL component (RFC 5545 §3.6.3)
3
+ *
4
+ * UID and DTSTAMP are required.
5
+ */
6
+ import { Component } from './component.js';
7
+ import { parseProperty } from './property.js';
8
+ export class Journal extends Component {
9
+ constructor() {
10
+ super('VJOURNAL');
11
+ }
12
+ // ── Required ─────────────────────────────────────────────────────────
13
+ get uid() {
14
+ return this.getProperty('UID')?.text ?? null;
15
+ }
16
+ set uid(v) {
17
+ this.setProperty('UID', v);
18
+ }
19
+ get dtstamp() {
20
+ const v = this.getValue('DTSTAMP');
21
+ return v && typeof v === 'object' && v.type === 'date-time' ? v : null;
22
+ }
23
+ set dtstamp(v) {
24
+ this.setProperty('DTSTAMP', v instanceof Date
25
+ ? { type: 'date-time', year: v.getUTCFullYear(), month: v.getUTCMonth() + 1, day: v.getUTCDate(), hour: v.getUTCHours(), minute: v.getUTCMinutes(), second: v.getUTCSeconds(), utc: true }
26
+ : v);
27
+ }
28
+ // ── Date/time ─────────────────────────────────────────────────────────
29
+ get dtstart() {
30
+ const v = this.getValue('DTSTART');
31
+ if (!v || typeof v !== 'object')
32
+ return null;
33
+ return v.type === 'date-time' || v.type === 'date' ? v : null;
34
+ }
35
+ set dtstart(v) {
36
+ if (v instanceof Date) {
37
+ this.setProperty('DTSTART', { type: 'date-time', year: v.getUTCFullYear(), month: v.getUTCMonth() + 1, day: v.getUTCDate(), hour: v.getUTCHours(), minute: v.getUTCMinutes(), second: v.getUTCSeconds(), utc: true });
38
+ }
39
+ else if (v.type === 'date') {
40
+ this.setProperty('DTSTART', v, { VALUE: 'DATE' });
41
+ }
42
+ else {
43
+ this.setProperty('DTSTART', v);
44
+ }
45
+ }
46
+ // ── Descriptive ──────────────────────────────────────────────────────
47
+ get summary() {
48
+ return this.getProperty('SUMMARY')?.text ?? null;
49
+ }
50
+ set summary(v) {
51
+ this.setProperty('SUMMARY', v);
52
+ }
53
+ get descriptions() {
54
+ return this.getProperties('DESCRIPTION');
55
+ }
56
+ addDescription(v) {
57
+ this.appendProperty('DESCRIPTION', v);
58
+ return this;
59
+ }
60
+ get status() {
61
+ return this.getProperty('STATUS')?.text ?? null;
62
+ }
63
+ set status(v) {
64
+ this.setProperty('STATUS', v);
65
+ }
66
+ get klass() {
67
+ return this.getProperty('CLASS')?.text ?? null;
68
+ }
69
+ set klass(v) {
70
+ this.setProperty('CLASS', v);
71
+ }
72
+ get url() {
73
+ return this.getProperty('URL')?.text ?? null;
74
+ }
75
+ set url(v) {
76
+ this.setProperty('URL', v);
77
+ }
78
+ get organizer() {
79
+ return this.getProperty('ORGANIZER')?.text ?? null;
80
+ }
81
+ set organizer(v) {
82
+ this.setProperty('ORGANIZER', v);
83
+ }
84
+ get sequence() {
85
+ return this.getProperty('SEQUENCE')?.number ?? null;
86
+ }
87
+ set sequence(v) {
88
+ this.setProperty('SEQUENCE', Math.max(0, Math.trunc(v)));
89
+ }
90
+ get created() {
91
+ const v = this.getValue('CREATED');
92
+ return v && typeof v === 'object' && v.type === 'date-time' ? v : null;
93
+ }
94
+ set created(v) {
95
+ this.setProperty('CREATED', v instanceof Date
96
+ ? { type: 'date-time', year: v.getUTCFullYear(), month: v.getUTCMonth() + 1, day: v.getUTCDate(), hour: v.getUTCHours(), minute: v.getUTCMinutes(), second: v.getUTCSeconds(), utc: true }
97
+ : v);
98
+ }
99
+ get lastModified() {
100
+ const v = this.getValue('LAST-MODIFIED');
101
+ return v && typeof v === 'object' && v.type === 'date-time' ? v : null;
102
+ }
103
+ set lastModified(v) {
104
+ this.setProperty('LAST-MODIFIED', v instanceof Date
105
+ ? { type: 'date-time', year: v.getUTCFullYear(), month: v.getUTCMonth() + 1, day: v.getUTCDate(), hour: v.getUTCHours(), minute: v.getUTCMinutes(), second: v.getUTCSeconds(), utc: true }
106
+ : v);
107
+ }
108
+ // ── Multi-occurrence ──────────────────────────────────────────────────
109
+ get attendees() {
110
+ return this.getProperties('ATTENDEE');
111
+ }
112
+ addAttendee(calAddress, params = {}) {
113
+ this.appendProperty('ATTENDEE', calAddress, params);
114
+ return this;
115
+ }
116
+ get categories() {
117
+ return this.getValues('CATEGORIES');
118
+ }
119
+ set categories(v) {
120
+ this.setProperty('CATEGORIES', v);
121
+ }
122
+ get rrules() {
123
+ return this.getProperties('RRULE')
124
+ .map((p) => p.scalar)
125
+ .filter((v) => typeof v === 'object' && v !== null && v.type === 'recur');
126
+ }
127
+ addRrule(v) {
128
+ this.appendProperty('RRULE', v);
129
+ return this;
130
+ }
131
+ // ── Validation ────────────────────────────────────────────────────────
132
+ toString() {
133
+ if (!this.uid)
134
+ throw new Error('VJOURNAL: UID is required');
135
+ if (!this.getProperty('DTSTAMP'))
136
+ throw new Error('VJOURNAL: DTSTAMP is required');
137
+ return super.toString();
138
+ }
139
+ // ── Factory ──────────────────────────────────────────────────────────
140
+ static fromRaw(props) {
141
+ const journal = new Journal();
142
+ for (const { name, params, value } of props) {
143
+ journal.addProperty(parseProperty(name, value, params));
144
+ }
145
+ return journal;
146
+ }
147
+ }
148
+ //# sourceMappingURL=journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal.js","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Tolerant iCalendar parser.
3
+ *
4
+ * Principles:
5
+ * - Accepts CRLF, LF, or bare CR line endings.
6
+ * - Handles folded lines.
7
+ * - Unknown components are stored as generic Component instances.
8
+ * - Unknown properties are stored with TEXT value.
9
+ * - Missing required wrappers are recovered from where possible.
10
+ * - Malformed property lines are skipped with a warning (no crash).
11
+ */
12
+ import { Calendar } from './calendar.js';
13
+ /**
14
+ * Parse an iCalendar string and return a Calendar object.
15
+ *
16
+ * Tolerant: if the input has no VCALENDAR wrapper (e.g. just a bare VEVENT)
17
+ * the content is wrapped in a synthetic Calendar.
18
+ *
19
+ * @throws Only on completely unparseable input that yields zero tokens.
20
+ */
21
+ export declare function parse(src: string): Calendar;
22
+ /**
23
+ * Parse an iCalendar string and return all top-level Calendar objects.
24
+ * Some feeds embed multiple VCALENDAR blocks in a single file.
25
+ */
26
+ export declare function parseAll(src: string): Calendar[];
27
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AA+GzC;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAe3C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAUhD"}
package/dist/parse.js ADDED
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Tolerant iCalendar parser.
3
+ *
4
+ * Principles:
5
+ * - Accepts CRLF, LF, or bare CR line endings.
6
+ * - Handles folded lines.
7
+ * - Unknown components are stored as generic Component instances.
8
+ * - Unknown properties are stored with TEXT value.
9
+ * - Missing required wrappers are recovered from where possible.
10
+ * - Malformed property lines are skipped with a warning (no crash).
11
+ */
12
+ import { tokenize } from './tokenize.js';
13
+ import { parseProperty } from './property.js';
14
+ import { Component } from './component.js';
15
+ import { Calendar } from './calendar.js';
16
+ import { Event } from './event.js';
17
+ import { Todo } from './todo.js';
18
+ import { Journal } from './journal.js';
19
+ import { FreeBusy } from './freebusy.js';
20
+ import { Timezone, buildTimezoneRule } from './timezone.js';
21
+ import { Alarm } from './alarm.js';
22
+ /** Build a raw component tree from the flat token stream. */
23
+ function buildTree(src) {
24
+ const tokens = tokenize(src);
25
+ const root = { type: 'ROOT', props: [], children: [] };
26
+ const stack = [root];
27
+ for (const token of tokens) {
28
+ const current = stack[stack.length - 1];
29
+ if (token.name === 'BEGIN') {
30
+ const node = {
31
+ type: token.value.toUpperCase().trim(),
32
+ props: [],
33
+ children: [],
34
+ };
35
+ current.children.push(node);
36
+ stack.push(node);
37
+ }
38
+ else if (token.name === 'END') {
39
+ if (stack.length > 1)
40
+ stack.pop();
41
+ // Tolerant: if stack is empty we ignore the END
42
+ }
43
+ else {
44
+ // Normalize params: ensure all values are strings (flatten single-element arrays)
45
+ const params = {};
46
+ for (const [k, v] of Object.entries(token.params)) {
47
+ params[k] = Array.isArray(v) ? v.join(',') : String(v);
48
+ }
49
+ current.props.push({ name: token.name, params, value: token.value });
50
+ }
51
+ }
52
+ return root.children;
53
+ }
54
+ // ── Component builders ────────────────────────────────────────────────────
55
+ function buildComponent(node) {
56
+ switch (node.type) {
57
+ case 'VCALENDAR': return buildCalendar(node);
58
+ case 'VEVENT': return buildEvent(node);
59
+ case 'VTODO': return buildTodo(node);
60
+ case 'VJOURNAL': return buildJournal(node);
61
+ case 'VFREEBUSY': return buildFreebusy(node);
62
+ case 'VTIMEZONE': return buildTimezone(node);
63
+ case 'VALARM': return buildAlarm(node);
64
+ case 'STANDARD':
65
+ case 'DAYLIGHT': return buildTimezoneRule(node.type, node.props);
66
+ default: return buildGeneric(node);
67
+ }
68
+ }
69
+ function buildCalendar(node) {
70
+ const children = node.children.map(buildComponent);
71
+ return Calendar.fromRaw(node.props, children);
72
+ }
73
+ function buildEvent(node) {
74
+ const children = node.children.map(buildComponent);
75
+ return Event.fromRaw(node.props, children);
76
+ }
77
+ function buildTodo(node) {
78
+ const children = node.children.map(buildComponent);
79
+ return Todo.fromRaw(node.props, children);
80
+ }
81
+ function buildJournal(node) {
82
+ return Journal.fromRaw(node.props);
83
+ }
84
+ function buildFreebusy(node) {
85
+ return FreeBusy.fromRaw(node.props);
86
+ }
87
+ function buildTimezone(node) {
88
+ const children = node.children.map(buildComponent);
89
+ return Timezone.fromRaw(node.props, children);
90
+ }
91
+ function buildAlarm(node) {
92
+ return Alarm.fromRaw(node.props);
93
+ }
94
+ function buildGeneric(node) {
95
+ const comp = new Component(node.type);
96
+ for (const { name, params, value } of node.props) {
97
+ comp.addProperty(parseProperty(name, value, params));
98
+ }
99
+ for (const child of node.children) {
100
+ comp.addComponent(buildComponent(child));
101
+ }
102
+ return comp;
103
+ }
104
+ // ── Public API ────────────────────────────────────────────────────────────
105
+ /**
106
+ * Parse an iCalendar string and return a Calendar object.
107
+ *
108
+ * Tolerant: if the input has no VCALENDAR wrapper (e.g. just a bare VEVENT)
109
+ * the content is wrapped in a synthetic Calendar.
110
+ *
111
+ * @throws Only on completely unparseable input that yields zero tokens.
112
+ */
113
+ export function parse(src) {
114
+ const roots = buildTree(src);
115
+ // Find the first VCALENDAR
116
+ const calNode = roots.find((n) => n.type === 'VCALENDAR');
117
+ if (calNode) {
118
+ return buildCalendar(calNode);
119
+ }
120
+ // Tolerant: no VCALENDAR wrapper — synthesize one
121
+ const cal = new Calendar();
122
+ for (const node of roots) {
123
+ cal.addComponent(buildComponent(node));
124
+ }
125
+ return cal;
126
+ }
127
+ /**
128
+ * Parse an iCalendar string and return all top-level Calendar objects.
129
+ * Some feeds embed multiple VCALENDAR blocks in a single file.
130
+ */
131
+ export function parseAll(src) {
132
+ const roots = buildTree(src);
133
+ const calendars = roots.filter((n) => n.type === 'VCALENDAR');
134
+ if (calendars.length > 0) {
135
+ return calendars.map(buildCalendar);
136
+ }
137
+ // No VCALENDAR blocks — wrap everything in one
138
+ return [parse(src)];
139
+ }
140
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAUnC,6DAA6D;AAC7D,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAY,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAChE,MAAM,KAAK,GAAc,CAAC,IAAI,CAAC,CAAC;IAEhC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QAEzC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAY;gBACpB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;gBACtC,KAAK,EAAE,EAAE;gBACT,QAAQ,EAAE,EAAE;aACb,CAAC;YACF,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,GAAG,EAAE,CAAC;YAClC,gDAAgD;QAClD,CAAC;aAAM,CAAC;YACN,kFAAkF;YAClF,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvE,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC,QAAQ,CAAC;AACvB,CAAC;AAED,6EAA6E;AAE7E,SAAS,cAAc,CAAC,IAAa;IACnC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,WAAW,CAAC,CAAE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9C,KAAK,QAAQ,CAAC,CAAK,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;QAC3C,KAAK,OAAO,CAAC,CAAM,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QAC1C,KAAK,UAAU,CAAC,CAAG,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;QAC7C,KAAK,WAAW,CAAC,CAAE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9C,KAAK,WAAW,CAAC,CAAE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9C,KAAK,QAAQ,CAAC,CAAK,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;QAC3C,KAAK,UAAU,CAAC;QAChB,KAAK,UAAU,CAAC,CAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACnE,OAAO,CAAC,CAAW,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,UAAU,CAAC,IAAa;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,SAAS,CAAC,IAAa;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,YAAY,CAAC,IAAa;IACjC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,UAAU,CAAC,IAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,YAAY,CAAC,IAAa;IACjC,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACjD,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6EAA6E;AAE7E;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CAAC,GAAW;IAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAE7B,2BAA2B;IAC3B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IAC1D,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,kDAAkD;IAClD,MAAM,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IAE9D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC;IAED,+CAA+C;IAC/C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * RFC 5545 property registry.
3
+ *
4
+ * Maps property names to their default value type, allowed alternative types,
5
+ * whether they accept a list of values, and which components they belong to.
6
+ */
7
+ export type ValueTypeName = 'TEXT' | 'INTEGER' | 'FLOAT' | 'BOOLEAN' | 'URI' | 'CAL-ADDRESS' | 'BINARY' | 'UTC-OFFSET' | 'DATE' | 'DATE-TIME' | 'TIME' | 'DURATION' | 'PERIOD' | 'RECUR' | 'GEO';
8
+ export interface PropertyDef {
9
+ /** Default value type when no VALUE= parameter is present */
10
+ readonly defaultType: ValueTypeName;
11
+ /** Additional allowed value types selectable via VALUE= parameter */
12
+ readonly allowedTypes?: readonly ValueTypeName[];
13
+ /**
14
+ * true → value is a comma-separated list of the same type
15
+ * false → single value
16
+ */
17
+ readonly multi?: boolean;
18
+ }
19
+ /**
20
+ * RFC 5545 §3.8 — Component Properties
21
+ * Includes deprecated but commonly encountered properties (EXRULE).
22
+ */
23
+ export declare const PROPERTY_REGISTRY: Readonly<Record<string, PropertyDef>>;
24
+ /** Look up a property definition; returns undefined for X- and unknown properties. */
25
+ export declare function getPropertyDef(name: string): PropertyDef | undefined;
26
+ /**
27
+ * Determine the effective value type for a content line.
28
+ * Respects VALUE= parameter override.
29
+ */
30
+ export declare function resolveValueType(name: string, params: Readonly<Record<string, string | readonly string[]>>): ValueTypeName;
31
+ //# sourceMappingURL=property-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-registry.d.ts","sourceRoot":"","sources":["../src/property-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,SAAS,GACT,OAAO,GACP,SAAS,GACT,KAAK,GACL,aAAa,GACb,QAAQ,GACR,YAAY,GACZ,MAAM,GACN,WAAW,GACX,MAAM,GACN,UAAU,GACV,QAAQ,GACR,OAAO,GACP,KAAK,CAAC;AAEV,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAiEnE,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,CAAC,GAC3D,aAAa,CAIf"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * RFC 5545 property registry.
3
+ *
4
+ * Maps property names to their default value type, allowed alternative types,
5
+ * whether they accept a list of values, and which components they belong to.
6
+ */
7
+ /**
8
+ * RFC 5545 §3.8 — Component Properties
9
+ * Includes deprecated but commonly encountered properties (EXRULE).
10
+ */
11
+ export const PROPERTY_REGISTRY = {
12
+ // ── Calendar Properties (§3.7) ─────────────────────────────────────────
13
+ CALSCALE: { defaultType: 'TEXT' },
14
+ METHOD: { defaultType: 'TEXT' },
15
+ PRODID: { defaultType: 'TEXT' },
16
+ VERSION: { defaultType: 'TEXT' },
17
+ // ── Descriptive Component Properties (§3.8.1) ──────────────────────────
18
+ ATTACH: { defaultType: 'URI', allowedTypes: ['BINARY'] },
19
+ CATEGORIES: { defaultType: 'TEXT', multi: true },
20
+ CLASS: { defaultType: 'TEXT' },
21
+ COMMENT: { defaultType: 'TEXT' },
22
+ DESCRIPTION: { defaultType: 'TEXT' },
23
+ GEO: { defaultType: 'GEO' },
24
+ LOCATION: { defaultType: 'TEXT' },
25
+ 'PERCENT-COMPLETE': { defaultType: 'INTEGER' },
26
+ PRIORITY: { defaultType: 'INTEGER' },
27
+ RESOURCES: { defaultType: 'TEXT', multi: true },
28
+ STATUS: { defaultType: 'TEXT' },
29
+ SUMMARY: { defaultType: 'TEXT' },
30
+ // ── Date and Time Component Properties (§3.8.2) ───────────────────────
31
+ COMPLETED: { defaultType: 'DATE-TIME' },
32
+ DTEND: { defaultType: 'DATE-TIME', allowedTypes: ['DATE'] },
33
+ DUE: { defaultType: 'DATE-TIME', allowedTypes: ['DATE'] },
34
+ DTSTART: { defaultType: 'DATE-TIME', allowedTypes: ['DATE'] },
35
+ DURATION: { defaultType: 'DURATION' },
36
+ FREEBUSY: { defaultType: 'PERIOD', multi: true },
37
+ TRANSP: { defaultType: 'TEXT' },
38
+ // ── Time Zone Component Properties (§3.8.3) ───────────────────────────
39
+ TZID: { defaultType: 'TEXT' },
40
+ TZNAME: { defaultType: 'TEXT' },
41
+ TZOFFSETFROM: { defaultType: 'UTC-OFFSET' },
42
+ TZOFFSETTO: { defaultType: 'UTC-OFFSET' },
43
+ TZURL: { defaultType: 'URI' },
44
+ // ── Relationship Component Properties (§3.8.4) ────────────────────────
45
+ ATTENDEE: { defaultType: 'CAL-ADDRESS' },
46
+ CONTACT: { defaultType: 'TEXT' },
47
+ ORGANIZER: { defaultType: 'CAL-ADDRESS' },
48
+ 'RECURRENCE-ID': { defaultType: 'DATE-TIME', allowedTypes: ['DATE'] },
49
+ 'RELATED-TO': { defaultType: 'TEXT' },
50
+ URL: { defaultType: 'URI' },
51
+ UID: { defaultType: 'TEXT' },
52
+ // ── Recurrence Component Properties (§3.8.5) ──────────────────────────
53
+ EXDATE: { defaultType: 'DATE-TIME', allowedTypes: ['DATE'], multi: true },
54
+ RDATE: { defaultType: 'DATE-TIME', allowedTypes: ['DATE', 'PERIOD'], multi: true },
55
+ RRULE: { defaultType: 'RECUR' },
56
+ EXRULE: { defaultType: 'RECUR' }, // deprecated, still common
57
+ // ── Alarm Component Properties (§3.8.6) ───────────────────────────────
58
+ ACTION: { defaultType: 'TEXT' },
59
+ REPEAT: { defaultType: 'INTEGER' },
60
+ TRIGGER: { defaultType: 'DURATION', allowedTypes: ['DATE-TIME'] },
61
+ // ── Change Management Component Properties (§3.8.7) ──────────────────
62
+ CREATED: { defaultType: 'DATE-TIME' },
63
+ DTSTAMP: { defaultType: 'DATE-TIME' },
64
+ 'LAST-MODIFIED': { defaultType: 'DATE-TIME' },
65
+ SEQUENCE: { defaultType: 'INTEGER' },
66
+ // ── Miscellaneous Component Properties (§3.8.8) ───────────────────────
67
+ 'REQUEST-STATUS': { defaultType: 'TEXT' },
68
+ };
69
+ /** Look up a property definition; returns undefined for X- and unknown properties. */
70
+ export function getPropertyDef(name) {
71
+ return PROPERTY_REGISTRY[name];
72
+ }
73
+ /**
74
+ * Determine the effective value type for a content line.
75
+ * Respects VALUE= parameter override.
76
+ */
77
+ export function resolveValueType(name, params) {
78
+ const override = typeof params['VALUE'] === 'string' ? params['VALUE'].toUpperCase() : undefined;
79
+ if (override)
80
+ return override;
81
+ return PROPERTY_REGISTRY[name]?.defaultType ?? 'TEXT';
82
+ }
83
+ //# sourceMappingURL=property-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-registry.js","sourceRoot":"","sources":["../src/property-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Property — a named, parametered, typed iCalendar property.
3
+ *
4
+ * Strict on construction (required for serialization).
5
+ * Tolerant when created from raw parsed data.
6
+ */
7
+ import type { ICalValue, ParsedProperty } from './types.js';
8
+ export declare class Property implements ParsedProperty {
9
+ readonly name: string;
10
+ readonly params: Readonly<Record<string, string | readonly string[]>>;
11
+ readonly value: ICalValue | readonly ICalValue[];
12
+ readonly rawValue: string;
13
+ constructor(name: string, value: ICalValue | readonly ICalValue[], params?: Readonly<Record<string, string | readonly string[]>>, rawValue?: string);
14
+ /** Get the first (or only) value as a plain value (null when the list is empty). */
15
+ get scalar(): ICalValue | null;
16
+ /** Get the value as an array (always). */
17
+ get list(): ICalValue[];
18
+ /** Convenience: get value as string (or null). */
19
+ get text(): string | null;
20
+ /** Convenience: get value as number (or null). */
21
+ get number(): number | null;
22
+ /** Convenience: get value as boolean. */
23
+ get boolean(): boolean | null;
24
+ /**
25
+ * Serialize this property to a single (unfolded) content line string.
26
+ * Throws if the value type cannot be serialized.
27
+ */
28
+ toContentLine(): string;
29
+ private serializeValue;
30
+ }
31
+ /**
32
+ * Parse a raw content-line value string into a typed Property.
33
+ * Tolerant: unknown value types fall back to TEXT.
34
+ */
35
+ export declare function parseProperty(name: string, rawValue: string, params: Readonly<Record<string, string | readonly string[]>>): Property;
36
+ //# sourceMappingURL=property.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property.d.ts","sourceRoot":"","sources":["../src/property.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK5D,qBAAa,QAAS,YAAW,cAAc;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACtE,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,SAAS,EAAE,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GAAG,SAAS,SAAS,EAAE,EACvC,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,CAAM,EACjE,QAAQ,SAAK;IAQf,oFAAoF;IACpF,IAAI,MAAM,IAAI,SAAS,GAAG,IAAI,CAI7B;IAED,0CAA0C;IAC1C,IAAI,IAAI,IAAI,SAAS,EAAE,CAItB;IAED,kDAAkD;IAClD,IAAI,IAAI,IAAI,MAAM,GAAG,IAAI,CAGxB;IAED,kDAAkD;IAClD,IAAI,MAAM,IAAI,MAAM,GAAG,IAAI,CAG1B;IAED,yCAAyC;IACzC,IAAI,OAAO,IAAI,OAAO,GAAG,IAAI,CAG5B;IAED;;;OAGG;IACH,aAAa,IAAI,MAAM;IAMvB,OAAO,CAAC,cAAc;CAsBvB;AAiBD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,CAAC,GAC3D,QAAQ,CAwBV"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Property — a named, parametered, typed iCalendar property.
3
+ *
4
+ * Strict on construction (required for serialization).
5
+ * Tolerant when created from raw parsed data.
6
+ */
7
+ import { CODECS, GEO } from './value-types.js';
8
+ import { getPropertyDef, resolveValueType } from './property-registry.js';
9
+ export class Property {
10
+ name;
11
+ params;
12
+ value;
13
+ rawValue;
14
+ constructor(name, value, params = {}, rawValue = '') {
15
+ this.name = name.toUpperCase();
16
+ this.value = value;
17
+ this.params = params;
18
+ this.rawValue = rawValue;
19
+ }
20
+ /** Get the first (or only) value as a plain value (null when the list is empty). */
21
+ get scalar() {
22
+ const v = this.value;
23
+ if (Array.isArray(v))
24
+ return v[0] ?? null;
25
+ return v;
26
+ }
27
+ /** Get the value as an array (always). */
28
+ get list() {
29
+ const v = this.value;
30
+ if (Array.isArray(v))
31
+ return [...v];
32
+ return [v];
33
+ }
34
+ /** Convenience: get value as string (or null). */
35
+ get text() {
36
+ const v = this.scalar;
37
+ return typeof v === 'string' ? v : null;
38
+ }
39
+ /** Convenience: get value as number (or null). */
40
+ get number() {
41
+ const v = this.scalar;
42
+ return typeof v === 'number' ? v : null;
43
+ }
44
+ /** Convenience: get value as boolean. */
45
+ get boolean() {
46
+ const v = this.scalar;
47
+ return typeof v === 'boolean' ? v : null;
48
+ }
49
+ /**
50
+ * Serialize this property to a single (unfolded) content line string.
51
+ * Throws if the value type cannot be serialized.
52
+ */
53
+ toContentLine() {
54
+ const paramStr = serializeParams(this.params);
55
+ const valueStr = this.serializeValue();
56
+ return `${this.name}${paramStr}:${valueStr}`;
57
+ }
58
+ serializeValue() {
59
+ const def = getPropertyDef(this.name);
60
+ const typeName = resolveValueType(this.name, this.params);
61
+ if (typeName === 'GEO') {
62
+ const v = this.scalar;
63
+ return GEO.serialize(v);
64
+ }
65
+ const codec = CODECS[typeName];
66
+ const serialize = (v) => {
67
+ if (codec)
68
+ return codec.serialize(v);
69
+ // Unknown / X- property: convert to string
70
+ return String(v ?? '');
71
+ };
72
+ if (def?.multi && Array.isArray(this.value)) {
73
+ return this.value.map(serialize).join(',');
74
+ }
75
+ return serialize(Array.isArray(this.value) ? (this.value[0] ?? '') : this.value);
76
+ }
77
+ }
78
+ function serializeParams(params) {
79
+ let result = '';
80
+ for (const [key, val] of Object.entries(params)) {
81
+ const valStr = Array.isArray(val) ? val.join(',') : val;
82
+ // Quote if contains special characters
83
+ const needsQuote = /[;:,]/.test(valStr);
84
+ result += `;${key}=${needsQuote ? `"${valStr}"` : valStr}`;
85
+ }
86
+ return result;
87
+ }
88
+ // ── Factory ───────────────────────────────────────────────────────────────
89
+ /**
90
+ * Parse a raw content-line value string into a typed Property.
91
+ * Tolerant: unknown value types fall back to TEXT.
92
+ */
93
+ export function parseProperty(name, rawValue, params) {
94
+ const typeName = resolveValueType(name, params);
95
+ const def = getPropertyDef(name);
96
+ try {
97
+ if (typeName === 'GEO') {
98
+ return new Property(name, GEO.parse(rawValue), params, rawValue);
99
+ }
100
+ const codec = CODECS[typeName] ?? CODECS['TEXT'];
101
+ if (def?.multi) {
102
+ // Split on unescaped commas
103
+ const parts = splitMultiValue(rawValue);
104
+ const values = parts.map((p) => codec.parse(p, params));
105
+ return new Property(name, values, params, rawValue);
106
+ }
107
+ const value = codec.parse(rawValue, params);
108
+ return new Property(name, value, params, rawValue);
109
+ }
110
+ catch {
111
+ // Tolerant fallback: store as raw string
112
+ return new Property(name, rawValue, params, rawValue);
113
+ }
114
+ }
115
+ /** Split a comma-separated multi-value string, respecting backslash escapes. */
116
+ function splitMultiValue(raw) {
117
+ const parts = [];
118
+ let current = '';
119
+ for (let i = 0; i < raw.length; i++) {
120
+ if (raw[i] === '\\' && i + 1 < raw.length) {
121
+ current += raw[i] + raw[i + 1];
122
+ i++;
123
+ }
124
+ else if (raw[i] === ',') {
125
+ parts.push(current);
126
+ current = '';
127
+ }
128
+ else {
129
+ current += raw[i];
130
+ }
131
+ }
132
+ parts.push(current);
133
+ return parts;
134
+ }
135
+ //# sourceMappingURL=property.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property.js","sourceRoot":"","sources":["../src/property.ts"],"names":[],"mappings":"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"}