calendaryjs 0.2.2 → 0.2.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/builder/index.cjs +338 -0
- package/dist/builder/index.d.cts +153 -0
- package/dist/builder/index.d.ts +153 -0
- package/dist/builder/index.js +326 -0
- package/dist/events-Bm7R9XFB.d.cts +590 -0
- package/dist/events-Bm7R9XFB.d.ts +590 -0
- package/dist/index.d.cts +3 -589
- package/dist/index.d.ts +3 -589
- package/package.json +13 -2
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// src/builder/builder.ts
|
|
2
|
+
function date(month, day) {
|
|
3
|
+
return { type: "const", fields: { month, day } };
|
|
4
|
+
}
|
|
5
|
+
var WEEKDAYS = {
|
|
6
|
+
sunday: 0,
|
|
7
|
+
monday: 1,
|
|
8
|
+
tuesday: 2,
|
|
9
|
+
wednesday: 3,
|
|
10
|
+
thursday: 4,
|
|
11
|
+
friday: 5,
|
|
12
|
+
saturday: 6
|
|
13
|
+
};
|
|
14
|
+
var MONTHS = {
|
|
15
|
+
jan: 1,
|
|
16
|
+
feb: 2,
|
|
17
|
+
mar: 3,
|
|
18
|
+
apr: 4,
|
|
19
|
+
may: 5,
|
|
20
|
+
jun: 6,
|
|
21
|
+
jul: 7,
|
|
22
|
+
aug: 8,
|
|
23
|
+
sep: 9,
|
|
24
|
+
oct: 10,
|
|
25
|
+
nov: 11,
|
|
26
|
+
dec: 12
|
|
27
|
+
};
|
|
28
|
+
function nth(n, weekday, month) {
|
|
29
|
+
const m = typeof month === "number" ? month : MONTHS[month];
|
|
30
|
+
if (!m) throw new Error(`unknown month "${month}"`);
|
|
31
|
+
return { type: "nth-weekday", fields: { nth: n, dayOfWeek: WEEKDAYS[weekday], month: m } };
|
|
32
|
+
}
|
|
33
|
+
var PLURAL = {
|
|
34
|
+
days: "day",
|
|
35
|
+
weeks: "week",
|
|
36
|
+
months: "month",
|
|
37
|
+
years: "year"
|
|
38
|
+
};
|
|
39
|
+
var BaseBuilder = class {
|
|
40
|
+
payload = {};
|
|
41
|
+
explicitId;
|
|
42
|
+
title(value) {
|
|
43
|
+
this.payload.title = value;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
id(value) {
|
|
47
|
+
this.explicitId = value;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
priority(value) {
|
|
51
|
+
this.payload.priority = value;
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
description(value) {
|
|
55
|
+
this.payload.description = value;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
location(value) {
|
|
59
|
+
this.payload.location = value;
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
url(value) {
|
|
63
|
+
this.payload.url = value;
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
color(value) {
|
|
67
|
+
this.payload.color = value;
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
icon(value) {
|
|
71
|
+
this.payload.icon = value;
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
source(value) {
|
|
75
|
+
this.payload.source = value;
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
status(value) {
|
|
79
|
+
this.payload.status = value;
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
allDay(value = true) {
|
|
83
|
+
this.payload.allDay = value;
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
/** Clock time(s): `.at("09:00")` or `.at("09:00", "10:30")`. */
|
|
87
|
+
at(start, end) {
|
|
88
|
+
this.payload.startTime = start;
|
|
89
|
+
if (end) this.payload.endTime = end;
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
/** Duration in minutes. */
|
|
93
|
+
duration(minutes) {
|
|
94
|
+
this.payload.duration = minutes;
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
keywords(...values) {
|
|
98
|
+
this.payload.keywords = values;
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
categories(...values) {
|
|
102
|
+
this.payload.categories = values;
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
/** Merge arbitrary metadata (later calls override earlier keys). */
|
|
106
|
+
metadata(data) {
|
|
107
|
+
const prev = this.payload.metadata ?? {};
|
|
108
|
+
this.payload.metadata = { ...prev, ...data };
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
/** A lead-time reminder before the occurrence. Accumulates. */
|
|
112
|
+
remind(before, opts) {
|
|
113
|
+
const trigger = (before.minutes ?? 0) + (before.hours ?? 0) * 60 + (before.days ?? 0) * 1440;
|
|
114
|
+
const reminders = this.payload.reminders ?? [];
|
|
115
|
+
reminders.push({
|
|
116
|
+
type: opts?.type ?? "notification",
|
|
117
|
+
trigger,
|
|
118
|
+
...opts?.message ? { message: opts.message } : {}
|
|
119
|
+
});
|
|
120
|
+
this.payload.reminders = reminders;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
/** Drop one occurrence (by its original date) → ICS EXDATE. */
|
|
124
|
+
skip(date2) {
|
|
125
|
+
this.exceptions()[date2] = { skip: true };
|
|
126
|
+
return this;
|
|
127
|
+
}
|
|
128
|
+
/** Replace properties for one occurrence → ICS RECURRENCE-ID. */
|
|
129
|
+
override(date2, props) {
|
|
130
|
+
this.exceptions()[date2] = { override: props };
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
/** Force-move one occurrence to another date. */
|
|
134
|
+
reschedule(fromDate, toDate) {
|
|
135
|
+
const map = this.payload.overrideDates ?? {};
|
|
136
|
+
map[fromDate] = toDate;
|
|
137
|
+
this.payload.overrideDates = map;
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
exceptions() {
|
|
141
|
+
const map = this.payload.exceptions ?? {};
|
|
142
|
+
this.payload.exceptions = map;
|
|
143
|
+
return map;
|
|
144
|
+
}
|
|
145
|
+
/** Explicit id, else a slug of the title, else throw. */
|
|
146
|
+
resolveId() {
|
|
147
|
+
const title = this.payload.title;
|
|
148
|
+
const id = this.explicitId ?? (title ? slug(title) : void 0);
|
|
149
|
+
if (!id) {
|
|
150
|
+
throw new Error("an event needs an .id(...), or a .title(...) to derive its id from");
|
|
151
|
+
}
|
|
152
|
+
return id;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
var EventBuilder = class extends BaseBuilder {
|
|
156
|
+
constructor(unit, interval) {
|
|
157
|
+
super();
|
|
158
|
+
this.unit = unit;
|
|
159
|
+
this.interval = interval;
|
|
160
|
+
}
|
|
161
|
+
unit;
|
|
162
|
+
interval;
|
|
163
|
+
selectorType;
|
|
164
|
+
fields = {};
|
|
165
|
+
on(...selectors) {
|
|
166
|
+
if (selectors.length > 1 || typeof selectors[0] === "string") {
|
|
167
|
+
if (!selectors.every((s) => typeof s === "string")) {
|
|
168
|
+
throw new Error(`.on(...) lists weekdays together with non-weekday selectors`);
|
|
169
|
+
}
|
|
170
|
+
if (this.unit !== "week") {
|
|
171
|
+
throw new Error(`.on("${selectors[0]}") (a weekday) needs every("week")`);
|
|
172
|
+
}
|
|
173
|
+
const indices = selectors.map((w) => {
|
|
174
|
+
if (!(w in WEEKDAYS)) throw new Error(`unknown weekday "${w}"`);
|
|
175
|
+
return WEEKDAYS[w];
|
|
176
|
+
});
|
|
177
|
+
const unique = [...new Set(indices)].sort((a, b) => a - b);
|
|
178
|
+
this.selectorType = "weekly";
|
|
179
|
+
this.fields.dayOfWeek = unique.length === 1 ? unique[0] : unique;
|
|
180
|
+
return this;
|
|
181
|
+
}
|
|
182
|
+
const selector = selectors[0];
|
|
183
|
+
if (typeof selector === "number") {
|
|
184
|
+
if (this.unit !== "month") {
|
|
185
|
+
throw new Error(`.on(${selector}) (a day of month) needs every("month")`);
|
|
186
|
+
}
|
|
187
|
+
this.selectorType = "monthly";
|
|
188
|
+
this.fields.day = selector;
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
191
|
+
const sel = selector;
|
|
192
|
+
if (this.unit !== "year") throw new Error(`.on(<selector>) needs every("year")`);
|
|
193
|
+
this.selectorType = sel.type;
|
|
194
|
+
Object.assign(this.fields, sel.fields);
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
/** Bound the recurrence: numbers → year range, date strings → date range. */
|
|
198
|
+
between(start, end) {
|
|
199
|
+
if (typeof start === "number") {
|
|
200
|
+
this.fields.startYear = start;
|
|
201
|
+
this.fields.endYear = end;
|
|
202
|
+
} else {
|
|
203
|
+
this.fields.startDate = start;
|
|
204
|
+
this.fields.endDate = end;
|
|
205
|
+
}
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
/** Upper bound only: a number → endYear, a date string → endDate. */
|
|
209
|
+
until(end) {
|
|
210
|
+
if (typeof end === "number") this.fields.endYear = end;
|
|
211
|
+
else this.fields.endDate = end;
|
|
212
|
+
return this;
|
|
213
|
+
}
|
|
214
|
+
exceptYears(...years) {
|
|
215
|
+
this.fields.excludeYears = years;
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
exceptMonths(...months) {
|
|
219
|
+
this.fields.excludeMonths = months;
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
exceptDates(...dates) {
|
|
223
|
+
this.fields.excludeDates = dates;
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
build() {
|
|
227
|
+
if (!this.selectorType) {
|
|
228
|
+
throw new Error(`every("${this.unit}") needs a position \u2014 call .on(...)`);
|
|
229
|
+
}
|
|
230
|
+
const config = {
|
|
231
|
+
type: this.selectorType,
|
|
232
|
+
id: this.resolveId(),
|
|
233
|
+
...this.fields,
|
|
234
|
+
...this.payload
|
|
235
|
+
};
|
|
236
|
+
if (this.interval > 1) {
|
|
237
|
+
if (this.selectorType !== "weekly" && this.selectorType !== "monthly") {
|
|
238
|
+
throw new Error(
|
|
239
|
+
`every(${this.interval}, \u2026) is not supported for "${this.selectorType}" yet`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
config.interval = this.interval;
|
|
243
|
+
}
|
|
244
|
+
return config;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
var RelativeBuilder = class extends BaseBuilder {
|
|
248
|
+
constructor(anchor) {
|
|
249
|
+
super();
|
|
250
|
+
this.anchor = anchor;
|
|
251
|
+
}
|
|
252
|
+
anchor;
|
|
253
|
+
days = 0;
|
|
254
|
+
weeks = 0;
|
|
255
|
+
plus(offset) {
|
|
256
|
+
this.days += offset.days ?? 0;
|
|
257
|
+
this.weeks += offset.weeks ?? 0;
|
|
258
|
+
return this;
|
|
259
|
+
}
|
|
260
|
+
minus(offset) {
|
|
261
|
+
this.days -= offset.days ?? 0;
|
|
262
|
+
this.weeks -= offset.weeks ?? 0;
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
build() {
|
|
266
|
+
const offset = {};
|
|
267
|
+
if (this.days) offset.days = this.days;
|
|
268
|
+
if (this.weeks) offset.weeks = this.weeks;
|
|
269
|
+
return {
|
|
270
|
+
type: "relative",
|
|
271
|
+
id: this.resolveId(),
|
|
272
|
+
anchor: this.anchor,
|
|
273
|
+
offset,
|
|
274
|
+
...this.payload
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var FixedBuilder = class extends BaseBuilder {
|
|
279
|
+
constructor(dateStr) {
|
|
280
|
+
super();
|
|
281
|
+
this.dateStr = dateStr;
|
|
282
|
+
}
|
|
283
|
+
dateStr;
|
|
284
|
+
build() {
|
|
285
|
+
const [year, month, day] = this.dateStr.split("-").map(Number);
|
|
286
|
+
if (!year || !month || !day) {
|
|
287
|
+
throw new Error(`once("${this.dateStr}") needs a YYYY-MM-DD date`);
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
type: "fixed",
|
|
291
|
+
id: this.resolveId(),
|
|
292
|
+
year,
|
|
293
|
+
month,
|
|
294
|
+
day,
|
|
295
|
+
...this.payload
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
function every(a, b) {
|
|
300
|
+
if (typeof a === "number") {
|
|
301
|
+
const unit = PLURAL[b];
|
|
302
|
+
if (!unit) throw new Error(`unknown unit "${b}"`);
|
|
303
|
+
return new EventBuilder(unit, a);
|
|
304
|
+
}
|
|
305
|
+
return new EventBuilder(a, 1);
|
|
306
|
+
}
|
|
307
|
+
function from(anchor) {
|
|
308
|
+
return new RelativeBuilder(anchor);
|
|
309
|
+
}
|
|
310
|
+
function once(dateStr) {
|
|
311
|
+
return new FixedBuilder(dateStr);
|
|
312
|
+
}
|
|
313
|
+
function weekly(weekday, ...moreWeekdays) {
|
|
314
|
+
return every("week").on(weekday, ...moreWeekdays);
|
|
315
|
+
}
|
|
316
|
+
function monthly(day) {
|
|
317
|
+
return every("month").on(day);
|
|
318
|
+
}
|
|
319
|
+
function yearly(month, day) {
|
|
320
|
+
return every("year").on(date(month, day));
|
|
321
|
+
}
|
|
322
|
+
function slug(value) {
|
|
323
|
+
return value.toLowerCase().replace(/đ/g, "d").normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "event";
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export { EventBuilder, FixedBuilder, RelativeBuilder, date, every, from, monthly, nth, once, weekly, yearly };
|