chore: clear pre-commit eslint warnings (unused symbols, stale disables, test any)
Cleans up the lint warnings the pre-commit hook surfaces, without any
behavioral change:
- Remove unused imports/vars/destructured props (parseISO, useEffect,
format, durMin, roles, daysInYear, ALLOWED_PLUGIN_FILES, continuesBefore,
isPushConnected, isSelected) and the now-unused parseDuration import.
- Drop three stale `// eslint-disable-next-line no-undef` directives that
no longer suppress anything (browser-navigation, smime/crypto-engine).
- recurrence-expansion.test.ts: replace 39 `as any` casts with a cast-only
`rule()` helper for partial recurrence-rule fixtures, typed access to
utcStart/utcEnd (now on CalendarEvent), and the source's
`Partial<CalendarEvent> & { excluded?: boolean }` for the excluded
override. No defaults are injected, so the expansion logic sees the same
partial rules as before (35 tests still green).
Remaining: 7 react-hooks/exhaustive-deps warnings are left as-is — adding
the missing deps changes effect/memo timing and needs per-hook review, not
a mechanical fix. tsc --noEmit clean; eslint 0 errors / 7 warnings.
This commit is contained in:
committed by
Linus Rath
parent
344795a8d9
commit
0b7203df0f
@@ -19,7 +19,7 @@ import {
|
|||||||
invalidateFrameOriginsCache,
|
invalidateFrameOriginsCache,
|
||||||
} from '@/lib/admin/csp-frame-origins';
|
} from '@/lib/admin/csp-frame-origins';
|
||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
import { MAX_PLUGIN_SIZE, MAX_THEME_SIZE, ALL_PERMISSIONS, ALLOWED_PLUGIN_FILES } from '@/lib/plugin-types';
|
import { MAX_PLUGIN_SIZE, MAX_THEME_SIZE, ALL_PERMISSIONS } from '@/lib/plugin-types';
|
||||||
import { sanitizeThemeCSS, validateThemeCSSSafety } from '@/lib/theme-loader';
|
import { sanitizeThemeCSS, validateThemeCSSSafety } from '@/lib/theme-loader';
|
||||||
import { configManager } from '@/lib/admin/config-manager';
|
import { configManager } from '@/lib/admin/config-manager';
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useTranslations, useFormatter } from "next-intl";
|
|||||||
import { format, isToday, isTomorrow, startOfDay } from "date-fns";
|
import { format, isToday, isTomorrow, startOfDay } from "date-fns";
|
||||||
import { MapPin, Users } from "lucide-react";
|
import { MapPin, Users } from "lucide-react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { parseDuration, getEventColor } from "./event-card";
|
import { getEventColor } from "./event-card";
|
||||||
import { getEventDayBounds, getEventEndDate, getEventStartDate, getPrimaryCalendarId } from "@/lib/calendar-utils";
|
import { getEventDayBounds, getEventEndDate, getEventStartDate, getPrimaryCalendarId } from "@/lib/calendar-utils";
|
||||||
import { getParticipantCount } from "@/lib/calendar-participants";
|
import { getParticipantCount } from "@/lib/calendar-participants";
|
||||||
import type { CalendarEvent, Calendar } from "@/lib/jmap/types";
|
import type { CalendarEvent, Calendar } from "@/lib/jmap/types";
|
||||||
@@ -147,7 +147,6 @@ export function CalendarAgendaView({
|
|||||||
const calendar = calId ? calendarMap.get(calId) : undefined;
|
const calendar = calId ? calendarMap.get(calId) : undefined;
|
||||||
const color = getEventColor(ev, calendar);
|
const color = getEventColor(ev, calendar);
|
||||||
const start = getEventStartDate(ev);
|
const start = getEventStartDate(ev);
|
||||||
const durMin = parseDuration(ev.duration);
|
|
||||||
const end = getEventEndDate(ev);
|
const end = getEventEndDate(ev);
|
||||||
const locationName = ev.locations
|
const locationName = ev.locations
|
||||||
? Object.values(ev.locations)[0]?.name
|
? Object.values(ev.locations)[0]?.name
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ function createEventDragPreview(title: string, timeRange: string, color: string)
|
|||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onMouseLeave, onContextMenu, isSelected, draggable: isDraggable, continuesBefore = false, continuesAfter = false, className, style }: EventCardProps) {
|
export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onMouseLeave, onContextMenu, isSelected, draggable: isDraggable, continuesAfter = false, className, style }: EventCardProps) {
|
||||||
const t = useTranslations("calendar");
|
const t = useTranslations("calendar");
|
||||||
const [isBeingDragged, setIsBeingDragged] = useState(false);
|
const [isBeingDragged, setIsBeingDragged] = useState(false);
|
||||||
const color = getEventColor(event, calendar);
|
const color = getEventColor(event, calendar);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
X, Clock, MapPin, Video, Users, Repeat, Bell, AlignLeft,
|
X, Clock, MapPin, Video, Users, Repeat, Bell, AlignLeft,
|
||||||
Pencil, Trash2, Copy, Send, Check,
|
Pencil, Trash2, Copy, Send, Check,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { format, isSameDay, parseISO } from "date-fns";
|
import { format, isSameDay } from "date-fns";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import type { CalendarEvent, Calendar, CalendarParticipant } from "@/lib/jmap/types";
|
import type { CalendarEvent, Calendar, CalendarParticipant } from "@/lib/jmap/types";
|
||||||
import { parseDuration, getEventColor } from "./event-card";
|
import { parseDuration, getEventColor } from "./event-card";
|
||||||
|
|||||||
@@ -617,7 +617,6 @@ export function EventModal({
|
|||||||
|
|
||||||
if (isAttendeeMode && event) {
|
if (isAttendeeMode && event) {
|
||||||
const startD = getEventStartDate(event);
|
const startD = getEventStartDate(event);
|
||||||
const durMin = parseDuration(event.duration);
|
|
||||||
const endD = getEventEndDate(event);
|
const endD = getEventEndDate(event);
|
||||||
const locationName = event.locations ? Object.values(event.locations)[0]?.name : null;
|
const locationName = event.locations ? Object.values(event.locations)[0]?.name : null;
|
||||||
const participants = getParticipantList(event);
|
const participants = getParticipantList(event);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useState, useCallback, useRef, useEffect } from "react";
|
|||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { X, Upload, Check, Loader2, RefreshCw, Globe } from "lucide-react";
|
import { X, Upload, Check, Loader2, RefreshCw, Globe } from "lucide-react";
|
||||||
import { format, parseISO } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import type { CalendarEvent, Calendar } from "@/lib/jmap/types";
|
import type { CalendarEvent, Calendar } from "@/lib/jmap/types";
|
||||||
import type { IJMAPClient } from '@/lib/jmap/client-interface';
|
import type { IJMAPClient } from '@/lib/jmap/client-interface';
|
||||||
import { getEventStartDate } from "@/lib/calendar-utils";
|
import { getEventStartDate } from "@/lib/calendar-utils";
|
||||||
|
|||||||
@@ -203,7 +203,6 @@ export function ContactDetail({ contact, onEdit, onDelete, onAddToGroup, onDupli
|
|||||||
const notes = contact.notes ? Object.values(contact.notes) : [];
|
const notes = contact.notes ? Object.values(contact.notes) : [];
|
||||||
const titles = contact.titles ? Object.values(contact.titles) : [];
|
const titles = contact.titles ? Object.values(contact.titles) : [];
|
||||||
const jobTitles = titles.filter(t => t.kind !== "role");
|
const jobTitles = titles.filter(t => t.kind !== "role");
|
||||||
const roles = titles.filter(t => t.kind === "role");
|
|
||||||
const onlineServices = contact.onlineServices ? Object.values(contact.onlineServices) : [];
|
const onlineServices = contact.onlineServices ? Object.values(contact.onlineServices) : [];
|
||||||
const anniversaries = contact.anniversaries ? Object.values(contact.anniversaries) : [];
|
const anniversaries = contact.anniversaries ? Object.values(contact.anniversaries) : [];
|
||||||
const keywords = contact.keywords ? Object.keys(contact.keywords).filter(k => contact.keywords![k]) : [];
|
const keywords = contact.keywords ? Object.keys(contact.keywords).filter(k => contact.keywords![k]) : [];
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useMemo, useCallback, useEffect, useRef } from "react";
|
import { useState, useMemo, useCallback, useRef } from "react";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { X, Plus, ChevronDown, ChevronRight, User, Building, MapPin, Globe, Cake, Heart, Tag, StickyNote, Mail, Phone, Calendar, UserCircle, Book, Camera, Trash2 } from "lucide-react";
|
import { X, Plus, ChevronDown, ChevronRight, User, Building, MapPin, Globe, Cake, Heart, Tag, StickyNote, Mail, Phone, Calendar, UserCircle, Book, Camera, Trash2 } from "lucide-react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ export function NavigationRail({
|
|||||||
collapsed = false,
|
collapsed = false,
|
||||||
className,
|
className,
|
||||||
quota,
|
quota,
|
||||||
isPushConnected,
|
|
||||||
onLogout,
|
onLogout,
|
||||||
onShowShortcuts,
|
onShowShortcuts,
|
||||||
onManageApps,
|
onManageApps,
|
||||||
|
|||||||
@@ -169,7 +169,6 @@ function getIconClass(isSelected: boolean, isVirtual: boolean, colorful: boolean
|
|||||||
function SidebarRowCounts({
|
function SidebarRowCounts({
|
||||||
unread,
|
unread,
|
||||||
total,
|
total,
|
||||||
isSelected,
|
|
||||||
onUnreadClick,
|
onUnreadClick,
|
||||||
}: {
|
}: {
|
||||||
unread?: number;
|
unread?: number;
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { expandRecurringEvents } from '../recurrence-expansion';
|
import { expandRecurringEvents } from '../recurrence-expansion';
|
||||||
import type { CalendarEvent } from '@/lib/jmap/types';
|
import type { CalendarEvent, CalendarRecurrenceRule } from '@/lib/jmap/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper: builds a recurrence-rule fixture from only the fields a test cares
|
||||||
|
* about. Cast-only (no defaults injected) so the expansion logic sees exactly
|
||||||
|
* the same partial rule the tests previously passed via `as any`.
|
||||||
|
*/
|
||||||
|
function rule(partial: Partial<CalendarRecurrenceRule>): CalendarRecurrenceRule {
|
||||||
|
return partial as CalendarRecurrenceRule;
|
||||||
|
}
|
||||||
|
|
||||||
/** Helper: create a minimal CalendarEvent for testing recurrence */
|
/** Helper: create a minimal CalendarEvent for testing recurrence */
|
||||||
function makeEvent(overrides: Partial<CalendarEvent> = {}): CalendarEvent {
|
function makeEvent(overrides: Partial<CalendarEvent> = {}): CalendarEvent {
|
||||||
@@ -41,7 +50,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
describe('daily frequency', () => {
|
describe('daily frequency', () => {
|
||||||
it('expands daily events within range', () => {
|
it('expands daily events within range', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-09T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-09T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -53,7 +62,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('respects interval', () => {
|
it('respects interval', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily', interval: 2 } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily', interval: 2 })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-12T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-12T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -65,7 +74,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('respects count', () => {
|
it('respects count', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily', count: 3 } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily', count: 3 })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-12-31T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-12-31T00:00:00');
|
||||||
expect(result).toHaveLength(3);
|
expect(result).toHaveLength(3);
|
||||||
@@ -73,7 +82,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('respects until', () => {
|
it('respects until', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily', until: '2025-01-08T09:00:00' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily', until: '2025-01-08T09:00:00' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-12-31T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-12-31T00:00:00');
|
||||||
expect(result).toHaveLength(3);
|
expect(result).toHaveLength(3);
|
||||||
@@ -86,7 +95,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
describe('weekly frequency', () => {
|
describe('weekly frequency', () => {
|
||||||
it('expands weekly with implicit byDay (same weekday as start)', () => {
|
it('expands weekly with implicit byDay (same weekday as start)', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
});
|
});
|
||||||
// Jan 6 is Monday, so every Monday
|
// Jan 6 is Monday, so every Monday
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-28T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-28T00:00:00');
|
||||||
@@ -100,11 +109,11 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('expands weekly with explicit byDay (MWF)', () => {
|
it('expands weekly with explicit byDay (MWF)', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'weekly',
|
frequency: 'weekly',
|
||||||
byDay: [{ day: 'mo' }, { day: 'we' }, { day: 'fr' }],
|
byDay: [{ day: 'mo' }, { day: 'we' }, { day: 'fr' }],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-13T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-13T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -116,12 +125,12 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('expands weekly with interval=2', () => {
|
it('expands weekly with interval=2', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'weekly',
|
frequency: 'weekly',
|
||||||
interval: 2,
|
interval: 2,
|
||||||
byDay: [{ day: 'mo' }],
|
byDay: [{ day: 'mo' }],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-02-03T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-02-03T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -138,7 +147,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands monthly with implicit byMonthDay', () => {
|
it('expands monthly with implicit byMonthDay', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-15T10:00:00',
|
start: '2025-01-15T10:00:00',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'monthly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'monthly' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -151,11 +160,11 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands monthly with byMonthDay', () => {
|
it('expands monthly with byMonthDay', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-01T08:00:00',
|
start: '2025-01-01T08:00:00',
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'monthly',
|
frequency: 'monthly',
|
||||||
byMonthDay: [1, 15],
|
byMonthDay: [1, 15],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2025-02-28T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2025-02-28T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -169,11 +178,11 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands monthly with negative byMonthDay (-1 = last day)', () => {
|
it('expands monthly with negative byMonthDay (-1 = last day)', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-31T08:00:00',
|
start: '2025-01-31T08:00:00',
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'monthly',
|
frequency: 'monthly',
|
||||||
byMonthDay: [-1],
|
byMonthDay: [-1],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
||||||
const days = result.map(e => e.start.substring(0, 10));
|
const days = result.map(e => e.start.substring(0, 10));
|
||||||
@@ -183,11 +192,11 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands monthly with byDay + nthOfPeriod (2nd Tuesday)', () => {
|
it('expands monthly with byDay + nthOfPeriod (2nd Tuesday)', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-14T09:00:00', // 2nd Tuesday
|
start: '2025-01-14T09:00:00', // 2nd Tuesday
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'monthly',
|
frequency: 'monthly',
|
||||||
byDay: [{ day: 'tu', nthOfPeriod: 2 }],
|
byDay: [{ day: 'tu', nthOfPeriod: 2 }],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
||||||
const days = result.map(e => e.start.substring(0, 10));
|
const days = result.map(e => e.start.substring(0, 10));
|
||||||
@@ -197,11 +206,11 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands monthly with byDay nthOfPeriod=-1 (last Friday)', () => {
|
it('expands monthly with byDay nthOfPeriod=-1 (last Friday)', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-31T09:00:00', // last Friday of Jan
|
start: '2025-01-31T09:00:00', // last Friday of Jan
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'monthly',
|
frequency: 'monthly',
|
||||||
byDay: [{ day: 'fr', nthOfPeriod: -1 }],
|
byDay: [{ day: 'fr', nthOfPeriod: -1 }],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2025-04-01T00:00:00');
|
||||||
const days = result.map(e => e.start.substring(0, 10));
|
const days = result.map(e => e.start.substring(0, 10));
|
||||||
@@ -216,7 +225,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands yearly on the same date', () => {
|
it('expands yearly on the same date', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2023-03-15T12:00:00',
|
start: '2023-03-15T12:00:00',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'yearly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'yearly' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2023-01-01T00:00:00', '2026-01-01T00:00:00');
|
const result = expand(event, '2023-01-01T00:00:00', '2026-01-01T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -229,12 +238,12 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands yearly with byMonth and byDay (last Friday of November = Thanksgiving-ish)', () => {
|
it('expands yearly with byMonth and byDay (last Friday of November = Thanksgiving-ish)', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-11-28T09:00:00', // last Friday of Nov 2025
|
start: '2025-11-28T09:00:00', // last Friday of Nov 2025
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'yearly',
|
frequency: 'yearly',
|
||||||
byMonth: ['11'],
|
byMonth: ['11'],
|
||||||
byDay: [{ day: 'fr', nthOfPeriod: -1 }],
|
byDay: [{ day: 'fr', nthOfPeriod: -1 }],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2028-01-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2028-01-01T00:00:00');
|
||||||
const days = result.map(e => e.start.substring(0, 10));
|
const days = result.map(e => e.start.substring(0, 10));
|
||||||
@@ -246,12 +255,12 @@ describe('expandRecurringEvents', () => {
|
|||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-07-04T00:00:00',
|
start: '2025-07-04T00:00:00',
|
||||||
showWithoutTime: true,
|
showWithoutTime: true,
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'yearly',
|
frequency: 'yearly',
|
||||||
byMonth: ['7'],
|
byMonth: ['7'],
|
||||||
byMonthDay: [4],
|
byMonthDay: [4],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2028-01-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2028-01-01T00:00:00');
|
||||||
expect(result).toHaveLength(3);
|
expect(result).toHaveLength(3);
|
||||||
@@ -265,12 +274,12 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('selects first and last from monthly byDay expansion', () => {
|
it('selects first and last from monthly byDay expansion', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-06T10:00:00',
|
start: '2025-01-06T10:00:00',
|
||||||
recurrenceRules: [{
|
recurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'monthly',
|
frequency: 'monthly',
|
||||||
byDay: [{ day: 'mo' }, { day: 'tu' }, { day: 'we' }, { day: 'th' }, { day: 'fr' }],
|
byDay: [{ day: 'mo' }, { day: 'tu' }, { day: 'we' }, { day: 'th' }, { day: 'fr' }],
|
||||||
bySetPosition: [1, -1], // first and last weekday of month
|
bySetPosition: [1, -1], // first and last weekday of month
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2025-03-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2025-03-01T00:00:00');
|
||||||
const days = result.map(e => e.start.substring(0, 10));
|
const days = result.map(e => e.start.substring(0, 10));
|
||||||
@@ -289,7 +298,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
describe('recurrenceOverrides', () => {
|
describe('recurrenceOverrides', () => {
|
||||||
it('applies overrides to matching occurrences', () => {
|
it('applies overrides to matching occurrences', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
recurrenceOverrides: {
|
recurrenceOverrides: {
|
||||||
'2025-01-07T09:00:00': { title: 'Modified' },
|
'2025-01-07T09:00:00': { title: 'Modified' },
|
||||||
},
|
},
|
||||||
@@ -301,9 +310,9 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('excludes occurrences marked as excluded', () => {
|
it('excludes occurrences marked as excluded', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
recurrenceOverrides: {
|
recurrenceOverrides: {
|
||||||
'2025-01-07T09:00:00': { excluded: true } as any,
|
'2025-01-07T09:00:00': { excluded: true } as Partial<CalendarEvent> & { excluded?: boolean },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-09T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-09T00:00:00');
|
||||||
@@ -313,7 +322,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('adds RDATE-style overrides not generated by rules', () => {
|
it('adds RDATE-style overrides not generated by rules', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
recurrenceOverrides: {
|
recurrenceOverrides: {
|
||||||
'2025-01-08T09:00:00': { title: 'Extra Wednesday' }, // Not a Monday
|
'2025-01-08T09:00:00': { title: 'Extra Wednesday' }, // Not a Monday
|
||||||
},
|
},
|
||||||
@@ -329,12 +338,12 @@ describe('expandRecurringEvents', () => {
|
|||||||
describe('excludedRecurrenceRules', () => {
|
describe('excludedRecurrenceRules', () => {
|
||||||
it('removes occurrences generated by excluded rules', () => {
|
it('removes occurrences generated by excluded rules', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
excludedRecurrenceRules: [{
|
excludedRecurrenceRules: [rule({
|
||||||
'@type': 'RecurrenceRule',
|
'@type': 'RecurrenceRule',
|
||||||
frequency: 'weekly',
|
frequency: 'weekly',
|
||||||
byDay: [{ day: 'tu' }],
|
byDay: [{ day: 'tu' }],
|
||||||
} as any],
|
})],
|
||||||
});
|
});
|
||||||
// Jan 6-12 2025: Mon-Sun, Tuesday Jan 7 excluded
|
// Jan 6-12 2025: Mon-Sun, Tuesday Jan 7 excluded
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-13T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-13T00:00:00');
|
||||||
@@ -353,7 +362,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands a daily series started years before the visible range', () => {
|
it('expands a daily series started years before the visible range', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2022-01-03T09:00:00',
|
start: '2022-01-03T09:00:00',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-06-02T00:00:00', '2025-06-05T00:00:00');
|
const result = expand(event, '2025-06-02T00:00:00', '2025-06-05T00:00:00');
|
||||||
expect(starts(result)).toEqual([
|
expect(starts(result)).toEqual([
|
||||||
@@ -366,7 +375,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('expands a weekly series started years before the visible range', () => {
|
it('expands a weekly series started years before the visible range', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2020-01-06T09:00:00', // Monday
|
start: '2020-01-06T09:00:00', // Monday
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-06-01T00:00:00', '2025-06-30T00:00:00');
|
const result = expand(event, '2025-06-01T00:00:00', '2025-06-30T00:00:00');
|
||||||
const days = result.map(e => e.start.substring(0, 10));
|
const days = result.map(e => e.start.substring(0, 10));
|
||||||
@@ -376,7 +385,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('still respects count for old series (no fast-forward shortcut)', () => {
|
it('still respects count for old series (no fast-forward shortcut)', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-06T09:00:00',
|
start: '2025-01-06T09:00:00',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily', count: 5 } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily', count: 5 })],
|
||||||
});
|
});
|
||||||
// Range far after the 5 occurrences ran out
|
// Range far after the 5 occurrences ran out
|
||||||
const result = expand(event, '2025-06-01T00:00:00', '2025-06-30T00:00:00');
|
const result = expand(event, '2025-06-01T00:00:00', '2025-06-30T00:00:00');
|
||||||
@@ -395,13 +404,13 @@ describe('expandRecurringEvents', () => {
|
|||||||
timeZone: 'America/New_York',
|
timeZone: 'America/New_York',
|
||||||
utcStart: '2025-03-03T15:00:00Z',
|
utcStart: '2025-03-03T15:00:00Z',
|
||||||
utcEnd: '2025-03-03T16:00:00Z',
|
utcEnd: '2025-03-03T16:00:00Z',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
} as Partial<CalendarEvent>);
|
} as Partial<CalendarEvent>);
|
||||||
const result = expand(event, '2025-03-03T00:00:00', '2025-03-17T00:00:00');
|
const result = expand(event, '2025-03-03T00:00:00', '2025-03-17T00:00:00');
|
||||||
const utcStarts = result.map(e => (e as any).utcStart);
|
const utcStarts = result.map(e => e.utcStart);
|
||||||
expect(utcStarts[0]).toBe('2025-03-03T15:00:00.000Z'); // EST: 10:00 -5
|
expect(utcStarts[0]).toBe('2025-03-03T15:00:00.000Z'); // EST: 10:00 -5
|
||||||
expect(utcStarts[1]).toBe('2025-03-10T14:00:00.000Z'); // EDT: 10:00 -4
|
expect(utcStarts[1]).toBe('2025-03-10T14:00:00.000Z'); // EDT: 10:00 -4
|
||||||
const utcEnds = result.map(e => (e as any).utcEnd);
|
const utcEnds = result.map(e => e.utcEnd);
|
||||||
expect(utcEnds[1]).toBe('2025-03-10T15:00:00.000Z');
|
expect(utcEnds[1]).toBe('2025-03-10T15:00:00.000Z');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -414,7 +423,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-06T00:00:00',
|
start: '2025-01-06T00:00:00',
|
||||||
showWithoutTime: true,
|
showWithoutTime: true,
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-28T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-28T00:00:00');
|
||||||
expect(result).toHaveLength(4); // 4 Mondays: 6, 13, 20, 27
|
expect(result).toHaveLength(4); // 4 Mondays: 6, 13, 20, 27
|
||||||
@@ -427,7 +436,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
describe('edge cases', () => {
|
describe('edge cases', () => {
|
||||||
it('does not exceed 500 occurrences', () => {
|
it('does not exceed 500 occurrences', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2030-01-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2030-01-01T00:00:00');
|
||||||
expect(result.length).toBeLessThanOrEqual(500);
|
expect(result.length).toBeLessThanOrEqual(500);
|
||||||
@@ -436,7 +445,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('handles invalid start date gracefully', () => {
|
it('handles invalid start date gracefully', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: 'invalid',
|
start: 'invalid',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-01T00:00:00', '2025-02-01T00:00:00');
|
const result = expand(event, '2025-01-01T00:00:00', '2025-02-01T00:00:00');
|
||||||
expect(result).toHaveLength(0);
|
expect(result).toHaveLength(0);
|
||||||
@@ -444,7 +453,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('generates synthetic IDs for occurrences', () => {
|
it('generates synthetic IDs for occurrences', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-08T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-08T00:00:00');
|
||||||
expect(result[0].id).toBe('evt1:2025-01-06T09:00:00');
|
expect(result[0].id).toBe('evt1:2025-01-06T09:00:00');
|
||||||
@@ -453,7 +462,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
|
|
||||||
it('preserves originalId pointing to master', () => {
|
it('preserves originalId pointing to master', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-08T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-08T00:00:00');
|
||||||
expect(result[0].originalId).toBe('evt1');
|
expect(result[0].originalId).toBe('evt1');
|
||||||
@@ -465,7 +474,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
id: 'master1',
|
id: 'master1',
|
||||||
uid: 'shared-uid',
|
uid: 'shared-uid',
|
||||||
start: '2025-01-06T09:00:00',
|
start: '2025-01-06T09:00:00',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
});
|
});
|
||||||
const override1 = makeEvent({
|
const override1 = makeEvent({
|
||||||
id: 'override1',
|
id: 'override1',
|
||||||
@@ -527,10 +536,10 @@ describe('expandRecurringEvents', () => {
|
|||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2026-09-01T12:00:00',
|
start: '2026-09-01T12:00:00',
|
||||||
utcStart: '2026-09-01T10:00:00Z',
|
utcStart: '2026-09-01T10:00:00Z',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2026-09-01T00:00:00', '2026-10-01T00:00:00');
|
const result = expand(event, '2026-09-01T00:00:00', '2026-10-01T00:00:00');
|
||||||
const utcStarts = result.map(e => (e as any).utcStart);
|
const utcStarts = result.map(e => e.utcStart);
|
||||||
// Each occurrence should have a unique utcStart
|
// Each occurrence should have a unique utcStart
|
||||||
expect(new Set(utcStarts).size).toBe(result.length);
|
expect(new Set(utcStarts).size).toBe(result.length);
|
||||||
// First occurrence keeps master's UTC offset relationship
|
// First occurrence keeps master's UTC offset relationship
|
||||||
@@ -545,10 +554,10 @@ describe('expandRecurringEvents', () => {
|
|||||||
duration: 'PT1H',
|
duration: 'PT1H',
|
||||||
utcStart: '2026-09-01T10:00:00Z',
|
utcStart: '2026-09-01T10:00:00Z',
|
||||||
utcEnd: '2026-09-01T11:00:00Z',
|
utcEnd: '2026-09-01T11:00:00Z',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'weekly' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'weekly' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2026-09-01T00:00:00', '2026-10-01T00:00:00');
|
const result = expand(event, '2026-09-01T00:00:00', '2026-10-01T00:00:00');
|
||||||
const utcEnds = result.map(e => (e as any).utcEnd);
|
const utcEnds = result.map(e => e.utcEnd);
|
||||||
// Each occurrence should have a unique utcEnd
|
// Each occurrence should have a unique utcEnd
|
||||||
expect(new Set(utcEnds).size).toBe(result.length);
|
expect(new Set(utcEnds).size).toBe(result.length);
|
||||||
expect(utcEnds[0]).toContain('2026-09-01');
|
expect(utcEnds[0]).toContain('2026-09-01');
|
||||||
@@ -559,7 +568,7 @@ describe('expandRecurringEvents', () => {
|
|||||||
it('does not set utcStart when master has none', () => {
|
it('does not set utcStart when master has none', () => {
|
||||||
const event = makeEvent({
|
const event = makeEvent({
|
||||||
start: '2025-01-06T09:00:00',
|
start: '2025-01-06T09:00:00',
|
||||||
recurrenceRules: [{ '@type': 'RecurrenceRule', frequency: 'daily' } as any],
|
recurrenceRules: [rule({ '@type': 'RecurrenceRule', frequency: 'daily' })],
|
||||||
});
|
});
|
||||||
const result = expand(event, '2025-01-06T00:00:00', '2025-01-08T00:00:00');
|
const result = expand(event, '2025-01-06T00:00:00', '2025-01-08T00:00:00');
|
||||||
expect(result[0].utcStart).toBeUndefined();
|
expect(result[0].utcStart).toBeUndefined();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { ContactCard, CalendarEvent, Calendar, PartialDate, Timestamp } from '@/lib/jmap/types';
|
import type { ContactCard, CalendarEvent, Calendar, PartialDate, Timestamp } from '@/lib/jmap/types';
|
||||||
import { getContactDisplayName } from '@/stores/contact-store';
|
import { getContactDisplayName } from '@/stores/contact-store';
|
||||||
import { format, eachYearOfInterval, parseISO } from 'date-fns';
|
import { eachYearOfInterval, parseISO } from 'date-fns';
|
||||||
|
|
||||||
export const BIRTHDAY_CALENDAR_ID = '__birthday-calendar__';
|
export const BIRTHDAY_CALENDAR_ID = '__birthday-calendar__';
|
||||||
export const BIRTHDAY_CALENDAR_COLOR = '#eab308'; // Yellow
|
export const BIRTHDAY_CALENDAR_COLOR = '#eab308'; // Yellow
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ export function getPathPrefix(locale?: string): string {
|
|||||||
* // Browser at /webmail/en/inbox → /webmail/api/jmap
|
* // Browser at /webmail/en/inbox → /webmail/api/jmap
|
||||||
* // Browser at /en/inbox → /api/jmap
|
* // Browser at /en/inbox → /api/jmap
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
export function apiFetch(input: string, init?: RequestInit): Promise<Response> {
|
export function apiFetch(input: string, init?: RequestInit): Promise<Response> {
|
||||||
if (input.startsWith('/') && !input.startsWith('//')) {
|
if (input.startsWith('/') && !input.startsWith('//')) {
|
||||||
return fetch(getPathPrefix() + input, init);
|
return fetch(getPathPrefix() + input, init);
|
||||||
|
|||||||
@@ -784,7 +784,6 @@ function nthWeekdayInYear(date: Date, nth: number): number {
|
|||||||
const firstYd = getDayOfYear(first);
|
const firstYd = getDayOfYear(first);
|
||||||
return Math.floor((yd - firstYd) / 7) + 1;
|
return Math.floor((yd - firstYd) / 7) + 1;
|
||||||
} else {
|
} else {
|
||||||
const daysInYear = isLeapYear(date.getFullYear()) ? 366 : 365;
|
|
||||||
const dec31 = new Date(date.getFullYear(), 11, 31);
|
const dec31 = new Date(date.getFullYear(), 11, 31);
|
||||||
let last = dec31;
|
let last = dec31;
|
||||||
while (last.getDay() !== weekday) last = addDays(last, -1);
|
while (last.getDay() !== weekday) last = addDays(last, -1);
|
||||||
|
|||||||
@@ -225,7 +225,6 @@ class Pkcs12CryptoEngine extends pkijs.CryptoEngine {
|
|||||||
const cryptoKey = await this.importKey(
|
const cryptoKey = await this.importKey(
|
||||||
'raw',
|
'raw',
|
||||||
keyData,
|
keyData,
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
{ name: algName, length: keyLen * 8 } as Algorithm,
|
{ name: algName, length: keyLen * 8 } as Algorithm,
|
||||||
false,
|
false,
|
||||||
['decrypt'],
|
['decrypt'],
|
||||||
@@ -234,7 +233,6 @@ class Pkcs12CryptoEngine extends pkijs.CryptoEngine {
|
|||||||
// Decrypt
|
// Decrypt
|
||||||
const ciphertext = parameters.encryptedContentInfo.getEncryptedContent();
|
const ciphertext = parameters.encryptedContentInfo.getEncryptedContent();
|
||||||
return this.decrypt(
|
return this.decrypt(
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
{ name: algName, iv: ivBytes } as Algorithm,
|
{ name: algName, iv: ivBytes } as Algorithm,
|
||||||
cryptoKey,
|
cryptoKey,
|
||||||
ciphertext,
|
ciphertext,
|
||||||
|
|||||||
Reference in New Issue
Block a user