Compare commits

...

59 Commits

Author SHA1 Message Date
Elian Doran
e868615fd5 chore(client): address requested changes 2026-03-10 22:19:50 +02:00
Elian Doran
80493a52be feat(video_player): move loop to center section 2026-03-10 20:46:28 +02:00
Elian Doran
3fed2ba42e feat(video_player): add zoom to fit button 2026-03-10 20:44:32 +02:00
Elian Doran
82592ada54 fix(video_player): unreadable controls on light theme 2026-03-10 20:36:03 +02:00
Elian Doran
5528701744 feat(video_player): indicate unsupported file formats 2026-03-10 20:33:47 +02:00
Elian Doran
0ca665fb85 chore(video_player): mention keys 2026-03-10 20:24:16 +02:00
Elian Doran
7eb452ed8b refactor(video_player): use translations 2026-03-10 20:22:03 +02:00
Elian Doran
d81dec94a9 feat(video_player): add keyboard shortcuts for toggling volume 2026-03-10 20:18:16 +02:00
Elian Doran
6631a4a806 feat(video_player): add shortcuts to just to beginning/end 2026-03-10 20:16:53 +02:00
Elian Doran
12f817c896 feat(video_player): add keyboard shortcut to toggle mute 2026-03-10 20:16:04 +02:00
Elian Doran
87229600d2 feat(video_player): keyboard shortcut to toggle full-screen 2026-03-10 20:15:10 +02:00
Elian Doran
471a46a030 feat(video_player): flash controls when pressing shortcuts 2026-03-10 20:14:11 +02:00
Elian Doran
41220eebd5 feat(video_player): arrow keys to seek 2026-03-10 20:11:56 +02:00
Elian Doran
755872277b feat(video_player): space to toggle play/pause 2026-03-10 20:10:40 +02:00
Elian Doran
2cb54d7021 fix(video_player): loop can get out of sync with external control 2026-03-10 20:09:33 +02:00
Elian Doran
5a16bafbbf fix(video_player): playback speed can get out of sync with external control 2026-03-10 20:08:17 +02:00
Elian Doran
fc6e9d89d9 fix(video_player): volume can get out of sync with external control 2026-03-10 20:07:45 +02:00
Elian Doran
8af35da279 feat(video_player): add loop button 2026-03-10 20:05:40 +02:00
Elian Doran
7107fec1a4 feat(video_player): add rotate button 2026-03-10 20:03:58 +02:00
Elian Doran
4bb662c5fb feat(video_player): button to toggle PIP 2026-03-10 20:00:38 +02:00
Elian Doran
89297b92f8 feat(video_player): click toggles play/pause instead of controls 2026-03-10 19:53:24 +02:00
Elian Doran
e019271e74 feat(video_player): hide immediately on play 2026-03-10 19:50:31 +02:00
Elian Doran
f6d61eefcc feat(video_player): don't hide controls if not playing 2026-03-10 19:48:21 +02:00
Elian Doran
fabc07be42 refactor(video_player): extract hiding visibility to hook 2026-03-10 19:47:25 +02:00
Elian Doran
bccfa7956c refactor(video_player): extract more buttons into separate components 2026-03-10 19:45:42 +02:00
Elian Doran
42a05f411b feat(video_player): basic toggle of the controls 2026-03-10 19:42:54 +02:00
Elian Doran
7ba7b98f5f feat(video_player): add playback speed indicator 2026-03-10 19:38:15 +02:00
Elian Doran
2132c2ab38 refactor(video_player): extract full screen to separate component 2026-03-10 19:29:00 +02:00
Elian Doran
2ce4d512e7 feat(video_player): add full screen button 2026-03-10 19:23:45 +02:00
Elian Doran
1258d32820 feat(video_player): add skip left/right buttons 2026-03-10 19:22:29 +02:00
Elian Doran
db763ba229 feat(video_player): improve style of bottom bar 2026-03-10 19:20:49 +02:00
Elian Doran
951fdaec70 chore(video_player): change button alignment 2026-03-10 19:17:51 +02:00
Elian Doran
4303f3687e refactor(video_player): extract seek bar & volume control 2026-03-10 19:12:52 +02:00
Elian Doran
540b0e0b83 feat(video_player): volume changer 2026-03-10 19:11:08 +02:00
Elian Doran
08a0326cb0 feat(video_player): add elapsed/remaining time 2026-03-10 19:05:59 +02:00
Elian Doran
8b0a45e4fd feat(video_player): add a trackbar for seeking the video 2026-03-10 18:57:58 +02:00
Elian Doran
0e0ad2ed73 feat(video_player): single play/pause button 2026-03-10 18:56:20 +02:00
Elian Doran
4c73f31aca feat(video_player): start adding custom controls (play/pause) 2026-03-10 18:54:53 +02:00
Elian Doran
6b2ae8fd12 feat(video_player): black background 2026-03-10 18:49:36 +02:00
Elian Doran
88d84fae1e refactor(video_player): extract to separate file 2026-03-10 18:48:54 +02:00
Elian Doran
cdc46faaad fix(board): add column not snappable on mobile 2026-03-10 18:41:53 +02:00
Elian Doran
24dbc79961 fix(board): clipped on horizontal scroll 2026-03-10 18:40:17 +02:00
Elian Doran
8cb58dcc45 fix(icon_packs): missing empty icon 2026-03-10 18:35:20 +02:00
Elian Doran
fe70b8aee6 fix(note_badges): saved indicator not disappearing if reduced motion was activated 2026-03-10 18:32:31 +02:00
Elian Doran
00f66cfb49 fix(popup_editor): note content no longer rendering
The commit f44b47ec added a hasTabBeenActive guard in NoteDetail that defers rendering until the tab has been active at least once. It initializes via noteContext?.isActive() and then listens for activeNoteChanged events.

The popup editor creates its own NoteContext("_popup-editor") which is never the activeNtxId in the tab manager — isActive() always returns false, and activeNoteChanged never fires for it. So hasTabBeenActive stays false forever, and the if (!type || !hasTabBeenActive) return guard at NoteDetail.tsx:64 prevents the note type widget from ever loading.
2026-03-10 18:32:31 +02:00
Elian Doran
3a4b080765 Table of contents fixes (#8933) 2026-03-10 18:31:24 +02:00
Elian Doran
41269ef987 chore(deps): update dependency express-rate-limit to v8.3.1 (#8981) 2026-03-10 08:30:06 +02:00
Elian Doran
e521c6a386 fix(deps): update dependency @mermaid-js/layout-elk to v0.2.1 (#8982) 2026-03-10 08:29:41 +02:00
Elian Doran
1c35a557c1 chore(deps): update pnpm to v10.32.0 (#8986) 2026-03-10 08:29:20 +02:00
Elian Doran
99eb8389c5 chore(deps): update typescript-eslint monorepo to v8.57.0 (#8987) 2026-03-10 08:29:03 +02:00
renovate[bot]
c5e560ef5b chore(deps): update typescript-eslint monorepo to v8.57.0 2026-03-10 02:13:50 +00:00
renovate[bot]
a7d7a078b1 chore(deps): update pnpm to v10.32.0 2026-03-10 02:12:47 +00:00
renovate[bot]
57bce62e48 fix(deps): update dependency @mermaid-js/layout-elk to v0.2.1 2026-03-10 02:09:36 +00:00
renovate[bot]
1c873394d5 chore(deps): update dependency express-rate-limit to v8.3.1 2026-03-10 02:08:32 +00:00
Elian Doran
aac4774326 Merge remote-tracking branch 'origin/main' into feature/toc_improvements 2026-03-08 12:20:53 +02:00
Elian Doran
d3337eab9c Merge branch 'main' into feature/toc_improvements 2026-03-05 21:05:17 +02:00
Elian Doran
8128a8192a refactor(ckeditor): address requested changes 2026-03-05 19:28:52 +02:00
Elian Doran
65514a6fd7 fix(toc): title is extracted before changes are made 2026-03-05 19:08:56 +02:00
Elian Doran
93a7f8c711 fix(toc): not reacting to attribute changes in CKEditor 2026-03-05 19:03:32 +02:00
24 changed files with 872 additions and 201 deletions

View File

@@ -14,7 +14,7 @@
"keywords": [],
"author": "Elian Doran <contact@eliandoran.me>",
"license": "AGPL-3.0-only",
"packageManager": "pnpm@10.31.0",
"packageManager": "pnpm@10.32.0",
"devDependencies": {
"@redocly/cli": "2.20.2",
"archiver": "7.0.1",

View File

@@ -25,7 +25,7 @@
"@fullcalendar/rrule": "6.1.20",
"@fullcalendar/timegrid": "6.1.20",
"@maplibre/maplibre-gl-leaflet": "0.1.3",
"@mermaid-js/layout-elk": "0.2.0",
"@mermaid-js/layout-elk": "0.2.1",
"@mind-elixir/node-menu": "5.0.1",
"@popperjs/core": "2.11.8",
"@preact/signals": "2.8.2",

View File

@@ -1036,6 +1036,25 @@
"file_preview_not_available": "File preview is not available for this file format.",
"too_big": "The preview only shows the first {{maxNumChars}} characters of the file for performance reasons. Download the file and open it externally to be able to see the entire content."
},
"video": {
"play": "Play (Space)",
"pause": "Pause (Space)",
"back-10s": "Back 10s (Left arrow key)",
"forward-30s": "Forward 30s",
"mute": "Mute (M)",
"unmute": "Unmute (M)",
"playback-speed": "Playback speed",
"loop": "Loop",
"disable-loop": "Disable loop",
"rotate": "Rotate",
"picture-in-picture": "Picture-in-picture",
"exit-picture-in-picture": "Exit picture-in-picture",
"fullscreen": "Fullscreen (F)",
"exit-fullscreen": "Exit fullscreen",
"unsupported-format": "Video preview is not available for this file format.",
"zoom-to-fit": "Zoom to fill",
"zoom-reset": "Reset zoom to fill"
},
"protected_session": {
"enter_password_instruction": "Showing protected note requires entering your password:",
"start_session_button": "Start protected session",

View File

@@ -41,7 +41,9 @@ export default function NoteDetail() {
const hasFixedTree = note && noteContext?.hoistedNoteId === "_lbMobileRoot" && isMobile() && note.noteId.startsWith("_lbMobile");
// Defer loading for tabs that haven't been active yet (e.g. on app refresh).
const [ hasTabBeenActive, setHasTabBeenActive ] = useState(() => noteContext?.isActive() ?? false);
// Special contexts (ntxId starting with "_", e.g. popup editor) are always considered active.
const isSpecialContext = ntxId?.startsWith("_") ?? false;
const [ hasTabBeenActive, setHasTabBeenActive ] = useState(() => isSpecialContext || (noteContext?.isActive() ?? false));
useEffect(() => {
if (!hasTabBeenActive && noteContext?.isActive()) {
setHasTabBeenActive(true);

View File

@@ -14,8 +14,7 @@
height: 100%;
display: flex;
gap: 1em;
margin-inline: var(--content-margin-inline);
padding-block: 4px;
padding: 4px var(--content-margin-inline);
align-items: flex-start;
overflow-x: auto;
}
@@ -42,7 +41,11 @@ body.mobile .board-view-container {
body.mobile .board-view-container .board-column {
width: 75vw;
max-width: 300px;
scroll-snap-align: center;
}
body.mobile .board-view-container .board-column,
body.mobile .board-view-container .board-add-column {
scroll-snap-align: center;
}
.board-view-container .board-column.drag-over {

View File

@@ -36,6 +36,10 @@
animation: fadeOut 250ms ease-in 5s forwards;
pointer-events: none;
}
body#trilium-app.motion-disabled &.saved {
animation: fadeOut 0s 5s forwards !important;
}
}
&.active-content-badge { --color: var(--badge-active-content-background-color); }
&.active-content-badge.disabled {

View File

@@ -1,6 +1,6 @@
import "./TableOfContents.css";
import { CKTextEditor, ModelElement } from "@triliumnext/ckeditor5";
import { attributeChangeAffectsHeading, CKTextEditor, ModelElement } from "@triliumnext/ckeditor5";
import clsx from "clsx";
import { useCallback, useEffect, useRef, useState } from "preact/hooks";
@@ -170,11 +170,14 @@ function EditableTextTableOfContents() {
const affectsHeadings = changes.some( change => {
return (
change.type === 'insert' || change.type === 'remove' || (change.type === 'attribute' && change.attributeKey === 'headingLevel')
change.type === 'insert' || change.type === 'remove' ||
(change.type === 'attribute' && attributeChangeAffectsHeading(change, textEditor))
);
});
if (affectsHeadings) {
setHeadings(extractTocFromTextEditor(textEditor));
requestAnimationFrame(() => {
setHeadings(extractTocFromTextEditor(textEditor));
});
}
};

View File

@@ -24,8 +24,7 @@
margin: 10px;
}
.note-detail-file > .pdf-preview,
.note-detail-file > .video-preview {
.note-detail-file > .pdf-preview {
width: 100%;
height: 100%;
flex-grow: 100;
@@ -38,4 +37,4 @@
right: 15px;
width: calc(100% - 30px);
transform: translateY(-50%);
}
}

View File

@@ -6,6 +6,7 @@ import { getUrlForDownload } from "../../services/open";
import Alert from "../react/Alert";
import { useNoteBlob } from "../react/hooks";
import PdfPreview from "./file/Pdf";
import VideoPreview from "./file/Video";
import { TypeWidgetProps } from "./type_widget";
const TEXT_MAX_NUM_CHARS = 5000;
@@ -42,17 +43,6 @@ function TextPreview({ content }: { content: string }) {
);
}
function VideoPreview({ note }: { note: FNote }) {
return (
<video
class="video-preview"
src={getUrlForDownload(`api/notes/${note.noteId}/open-partial`)}
datatype={note?.mime}
controls
/>
);
}
function AudioPreview({ note }: { note: FNote }) {
return (
<audio

View File

@@ -0,0 +1,114 @@
.note-detail-file > .video-preview-wrapper {
width: 100%;
height: 100%;
position: relative;
background-color: black;
.video-preview {
background-color: black;
width: 100%;
height: 100%;
}
&.controls-hidden {
cursor: pointer;
.video-preview-controls {
opacity: 0;
pointer-events: none;
}
}
.video-preview-controls {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 1.25em;
display: flex;
flex-direction: column;
gap: 0.5em;
background: rgba(0, 0, 0, 0.5);
color: white;
--icon-button-hover-color: white;
--icon-button-hover-background: rgba(255, 255, 255, 0.2);
opacity: 1;
transition: opacity 300ms ease;
.video-buttons-row {
display: flex;
> * {
flex: 1;
align-items: center;
gap: 0.5em;
display: flex;
}
.spacer {
width: var(--icon-button-size, 32px);
height: var(--icon-button-size, 32px);
}
.center {
justify-content: center;
}
.right {
display: flex;
justify-content: flex-end;
}
.play-button {
--icon-button-size: 48px;
}
}
}
.video-seekbar-row {
display: flex;
align-items: center;
gap: 0.5em;
}
.video-trackbar {
flex: 1;
cursor: pointer;
}
.video-time {
font-size: 0.85em;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.video-volume-row {
display: flex;
align-items: center;
gap: 0.25em;
}
.video-volume-slider {
width: 80px;
cursor: pointer;
}
.speed-dropdown {
position: relative;
.tn-icon {
transform: translateY(-10%);
}
.video-speed-label {
position: absolute;
bottom: 0;
left: 0;
right: 0;
transform: translateY(15%);
text-align: center;
font-size: 0.6rem;
font-variant-numeric: tabular-nums;
}
}
}

View File

@@ -0,0 +1,514 @@
import "./Video.css";
import { RefObject } from "preact";
import { useCallback, useEffect, useRef, useState } from "preact/hooks";
import FNote from "../../../entities/fnote";
import { t } from "../../../services/i18n";
import { getUrlForDownload } from "../../../services/open";
import ActionButton from "../../react/ActionButton";
import Dropdown from "../../react/Dropdown";
import Icon from "../../react/Icon";
import NoItems from "../../react/NoItems";
function formatTime(seconds: number): string {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, "0")}`;
}
const AUTO_HIDE_DELAY = 3000;
export default function VideoPreview({ note }: { note: FNote }) {
const wrapperRef = useRef<HTMLDivElement>(null);
const videoRef = useRef<HTMLVideoElement>(null);
const [playing, setPlaying] = useState(false);
const [error, setError] = useState(false);
const { visible: controlsVisible, onMouseMove, flash: flashControls } = useAutoHideControls(videoRef, playing);
useEffect(() => setError(false), [note.noteId]);
const onError = useCallback(() => setError(true), []);
const togglePlayback = useCallback(() => {
const video = videoRef.current;
if (!video) return;
if (video.paused) {
video.play();
} else {
video.pause();
}
}, []);
const onVideoClick = useCallback((e: MouseEvent) => {
if ((e.target as HTMLElement).closest(".video-preview-controls")) return;
togglePlayback();
}, [togglePlayback]);
const onKeyDown = useCallback((e: KeyboardEvent) => {
const video = videoRef.current;
if (!video) return;
switch (e.key) {
case " ":
e.preventDefault();
togglePlayback();
flashControls();
break;
case "ArrowLeft":
e.preventDefault();
video.currentTime = Math.max(0, video.currentTime - (e.ctrlKey ? 60 : 10));
flashControls();
break;
case "ArrowRight":
e.preventDefault();
video.currentTime = Math.min(video.duration, video.currentTime + (e.ctrlKey ? 60 : 10));
flashControls();
break;
case "f":
case "F":
e.preventDefault();
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
wrapperRef.current?.requestFullscreen();
}
break;
case "m":
case "M":
e.preventDefault();
video.muted = !video.muted;
flashControls();
break;
case "ArrowUp":
e.preventDefault();
video.volume = Math.min(1, video.volume + 0.05);
flashControls();
break;
case "ArrowDown":
e.preventDefault();
video.volume = Math.max(0, video.volume - 0.05);
flashControls();
break;
case "Home":
e.preventDefault();
video.currentTime = 0;
flashControls();
break;
case "End":
e.preventDefault();
video.currentTime = video.duration;
flashControls();
break;
}
}, [togglePlayback, flashControls]);
if (error) {
return <NoItems icon="bx bx-video-off" text={t("video.unsupported-format")} />;
}
return (
<div ref={wrapperRef} className={`video-preview-wrapper ${controlsVisible ? "" : "controls-hidden"}`} tabIndex={0} onClick={onVideoClick} onKeyDown={onKeyDown} onMouseMove={onMouseMove}>
<video
ref={videoRef}
class="video-preview"
src={getUrlForDownload(`api/notes/${note.noteId}/open-partial`)}
datatype={note?.mime}
onPlay={() => setPlaying(true)}
onPause={() => setPlaying(false)}
onError={onError}
/>
<div className="video-preview-controls">
<SeekBar videoRef={videoRef} />
<div class="video-buttons-row">
<div className="left">
<PlaybackSpeed videoRef={videoRef} />
<RotateButton videoRef={videoRef} />
</div>
<div className="center">
<div className="spacer" />
<SkipButton videoRef={videoRef} seconds={-10} icon="bx bx-rewind" text={t("video.back-10s")} />
<PlayPauseButton videoRef={videoRef} playing={playing} />
<SkipButton videoRef={videoRef} seconds={30} icon="bx bx-fast-forward" text={t("video.forward-30s")} />
<LoopButton videoRef={videoRef} />
</div>
<div className="right">
<VolumeControl videoRef={videoRef} />
<ZoomToFitButton videoRef={videoRef} />
<PictureInPictureButton videoRef={videoRef} />
<FullscreenButton targetRef={wrapperRef} />
</div>
</div>
</div>
</div>
);
}
function useAutoHideControls(videoRef: RefObject<HTMLVideoElement>, playing: boolean) {
const [visible, setVisible] = useState(true);
const hideTimerRef = useRef<ReturnType<typeof setTimeout>>();
const scheduleHide = useCallback(() => {
clearTimeout(hideTimerRef.current);
if (videoRef.current && !videoRef.current.paused) {
hideTimerRef.current = setTimeout(() => setVisible(false), AUTO_HIDE_DELAY);
}
}, []);
const onMouseMove = useCallback(() => {
setVisible(true);
scheduleHide();
}, [scheduleHide]);
// Hide immediately when playback starts, show when paused.
useEffect(() => {
if (playing) {
setVisible(false);
} else {
clearTimeout(hideTimerRef.current);
setVisible(true);
}
return () => clearTimeout(hideTimerRef.current);
}, [playing, scheduleHide]);
return { visible, onMouseMove, flash: onMouseMove };
}
function PlayPauseButton({ videoRef, playing }: { videoRef: RefObject<HTMLVideoElement>, playing: boolean }) {
const togglePlayback = () => {
const video = videoRef.current;
if (!video) return;
if (video.paused) {
video.play();
} else {
video.pause();
}
};
return (
<ActionButton
className="play-button"
icon={playing ? "bx bx-pause" : "bx bx-play"}
text={playing ? t("video.pause") : t("video.play")}
onClick={togglePlayback}
/>
);
}
function SkipButton({ videoRef, seconds, icon, text }: { videoRef: RefObject<HTMLVideoElement>, seconds: number, icon: string, text: string }) {
const skip = () => {
const video = videoRef.current;
if (!video) return;
video.currentTime = Math.max(0, Math.min(video.duration, video.currentTime + seconds));
};
return (
<ActionButton icon={icon} text={text} onClick={skip} />
);
}
function SeekBar({ videoRef }: { videoRef: RefObject<HTMLVideoElement> }) {
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
useEffect(() => {
const video = videoRef.current;
if (!video) return;
const onTimeUpdate = () => setCurrentTime(video.currentTime);
const onDurationChange = () => setDuration(video.duration);
video.addEventListener("timeupdate", onTimeUpdate);
video.addEventListener("durationchange", onDurationChange);
return () => {
video.removeEventListener("timeupdate", onTimeUpdate);
video.removeEventListener("durationchange", onDurationChange);
};
}, []);
const onSeek = (e: Event) => {
const video = videoRef.current;
if (!video) return;
video.currentTime = parseFloat((e.target as HTMLInputElement).value);
};
return (
<div class="video-seekbar-row">
<span class="video-time">{formatTime(currentTime)}</span>
<input
type="range"
class="video-trackbar"
min={0}
max={duration || 0}
step={0.1}
value={currentTime}
onInput={onSeek}
/>
<span class="video-time">-{formatTime(Math.max(0, duration - currentTime))}</span>
</div>
);
}
function VolumeControl({ videoRef }: { videoRef: RefObject<HTMLVideoElement> }) {
const [volume, setVolume] = useState(() => videoRef.current?.volume ?? 1);
const [muted, setMuted] = useState(() => videoRef.current?.muted ?? false);
// Sync state when the video element changes volume externally.
useEffect(() => {
const video = videoRef.current;
if (!video) return;
setVolume(video.volume);
setMuted(video.muted);
const onVolumeChange = () => {
setVolume(video.volume);
setMuted(video.muted);
};
video.addEventListener("volumechange", onVolumeChange);
return () => video.removeEventListener("volumechange", onVolumeChange);
}, []);
const onVolumeChange = (e: Event) => {
const video = videoRef.current;
if (!video) return;
const val = parseFloat((e.target as HTMLInputElement).value);
video.volume = val;
setVolume(val);
if (val > 0 && video.muted) {
video.muted = false;
setMuted(false);
}
};
const toggleMute = () => {
const video = videoRef.current;
if (!video) return;
video.muted = !video.muted;
setMuted(video.muted);
};
return (
<div class="video-volume-row">
<ActionButton
icon={muted || volume === 0 ? "bx bx-volume-mute" : volume < 0.5 ? "bx bx-volume-low" : "bx bx-volume-full"}
text={muted ? t("video.unmute") : t("video.mute")}
onClick={toggleMute}
/>
<input
type="range"
class="video-volume-slider"
min={0}
max={1}
step={0.05}
value={muted ? 0 : volume}
onInput={onVolumeChange}
/>
</div>
);
}
const PLAYBACK_SPEEDS = [0.5, 1, 1.25, 1.5, 2];
function PlaybackSpeed({ videoRef }: { videoRef: RefObject<HTMLVideoElement> }) {
const [speed, setSpeed] = useState(() => videoRef.current?.playbackRate ?? 1);
useEffect(() => {
const video = videoRef.current;
if (!video) return;
setSpeed(video.playbackRate);
const onRateChange = () => setSpeed(video.playbackRate);
video.addEventListener("ratechange", onRateChange);
return () => video.removeEventListener("ratechange", onRateChange);
}, []);
const selectSpeed = (rate: number) => {
const video = videoRef.current;
if (!video) return;
video.playbackRate = rate;
setSpeed(rate);
};
return (
<Dropdown
iconAction
hideToggleArrow
buttonClassName="speed-dropdown"
text={<>
<Icon icon="bx bx-tachometer" />
<span class="video-speed-label">{speed}x</span>
</>}
title={t("video.playback-speed")}
>
{PLAYBACK_SPEEDS.map((rate) => (
<li key={rate}>
<button
class={`dropdown-item ${rate === speed ? "active" : ""}`}
onClick={() => selectSpeed(rate)}
>
{rate}x
</button>
</li>
))}
</Dropdown>
);
}
function LoopButton({ videoRef }: { videoRef: RefObject<HTMLVideoElement> }) {
const [loop, setLoop] = useState(() => videoRef.current?.loop ?? false);
useEffect(() => {
const video = videoRef.current;
if (!video) return;
setLoop(video.loop);
const observer = new MutationObserver(() => setLoop(video.loop));
observer.observe(video, { attributes: true, attributeFilter: ["loop"] });
return () => observer.disconnect();
}, []);
const toggle = () => {
const video = videoRef.current;
if (!video) return;
video.loop = !video.loop;
setLoop(video.loop);
};
return (
<ActionButton
className={loop ? "active" : ""}
icon="bx bx-repeat"
text={loop ? t("video.disable-loop") : t("video.loop")}
onClick={toggle}
/>
);
}
function RotateButton({ videoRef }: { videoRef: RefObject<HTMLVideoElement> }) {
const [rotation, setRotation] = useState(0);
const rotate = () => {
const video = videoRef.current;
if (!video) return;
const next = (rotation + 90) % 360;
setRotation(next);
const isSideways = next === 90 || next === 270;
if (isSideways) {
// Scale down so the rotated video fits within its container.
const container = video.parentElement;
if (container) {
const ratio = container.clientWidth / container.clientHeight;
video.style.transform = `rotate(${next}deg) scale(${1 / ratio})`;
} else {
video.style.transform = `rotate(${next}deg)`;
}
} else {
video.style.transform = next === 0 ? "" : `rotate(${next}deg)`;
}
};
return (
<ActionButton
icon="bx bx-rotate-right"
text={t("video.rotate")}
onClick={rotate}
/>
);
}
function ZoomToFitButton({ videoRef }: { videoRef: RefObject<HTMLVideoElement> }) {
const [fitted, setFitted] = useState(false);
const toggle = () => {
const video = videoRef.current;
if (!video) return;
const next = !fitted;
video.style.objectFit = next ? "cover" : "";
setFitted(next);
};
return (
<ActionButton
className={fitted ? "active" : ""}
icon={fitted ? "bx bx-collapse" : "bx bx-expand"}
text={fitted ? t("video.zoom-reset") : t("video.zoom-to-fit")}
onClick={toggle}
/>
);
}
function PictureInPictureButton({ videoRef }: { videoRef: RefObject<HTMLVideoElement> }) {
const [active, setActive] = useState(false);
// The standard PiP API is only supported in Chromium-based browsers.
// Firefox uses its own proprietary PiP implementation.
const supported = "requestPictureInPicture" in HTMLVideoElement.prototype;
useEffect(() => {
const video = videoRef.current;
if (!video || !supported) return;
const onEnter = () => setActive(true);
const onLeave = () => setActive(false);
video.addEventListener("enterpictureinpicture", onEnter);
video.addEventListener("leavepictureinpicture", onLeave);
return () => {
video.removeEventListener("enterpictureinpicture", onEnter);
video.removeEventListener("leavepictureinpicture", onLeave);
};
}, [supported]);
if (!supported) return null;
const toggle = () => {
const video = videoRef.current;
if (!video) return;
if (document.pictureInPictureElement) {
document.exitPictureInPicture();
} else {
video.requestPictureInPicture();
}
};
return (
<ActionButton
icon={active ? "bx bx-exit" : "bx bx-window-open"}
text={active ? t("video.exit-picture-in-picture") : t("video.picture-in-picture")}
onClick={toggle}
/>
);
}
function FullscreenButton({ targetRef }: { targetRef: RefObject<HTMLElement> }) {
const [isFullscreen, setIsFullscreen] = useState(false);
useEffect(() => {
const onFullscreenChange = () => setIsFullscreen(!!document.fullscreenElement);
document.addEventListener("fullscreenchange", onFullscreenChange);
return () => document.removeEventListener("fullscreenchange", onFullscreenChange);
}, []);
const toggleFullscreen = () => {
const target = targetRef.current;
if (!target) return;
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
target.requestFullscreen();
}
};
return (
<ActionButton
icon={isFullscreen ? "bx bx-exit-fullscreen" : "bx bx-fullscreen"}
text={isFullscreen ? t("video.exit-fullscreen") : t("video.fullscreen")}
onClick={toggleFullscreen}
/>
);
}

View File

@@ -89,7 +89,7 @@
"express": "5.2.1",
"express-http-proxy": "2.1.2",
"express-openid-connect": "2.19.4",
"express-rate-limit": "8.3.0",
"express-rate-limit": "8.3.1",
"express-session": "1.19.0",
"file-uri-to-path": "2.0.0",
"fs-extra": "11.3.4",

View File

@@ -10449,6 +10449,12 @@
"terms": [
"virus-block"
]
},
"bx-empty": {
"glyph": "",
"terms": [
"empty"
]
}
}
}

View File

@@ -13,7 +13,7 @@
"postinstall": "wxt prepare"
},
"keywords": [],
"packageManager": "pnpm@10.31.0",
"packageManager": "pnpm@10.32.0",
"devDependencies": {
"@wxt-dev/auto-icons": "1.1.1",
"wxt": "0.20.18"

View File

@@ -73,7 +73,7 @@
"tslib": "2.8.1",
"tsx": "4.21.0",
"typescript": "5.9.3",
"typescript-eslint": "8.56.1",
"typescript-eslint": "8.57.0",
"upath": "2.0.1",
"vite": "7.3.1",
"vite-plugin-dts": "4.5.4",
@@ -93,7 +93,7 @@
"url": "https://github.com/TriliumNext/Trilium/issues"
},
"homepage": "https://triliumnotes.org",
"packageManager": "pnpm@10.31.0",
"packageManager": "pnpm@10.32.0",
"pnpm": {
"patchedDependencies": {
"@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch",

View File

@@ -24,8 +24,8 @@
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "5.0.1",
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/eslint-plugin": "8.57.0",
"@typescript-eslint/parser": "8.57.0",
"@vitest/browser": "4.0.18",
"@vitest/coverage-istanbul": "4.0.18",
"ckeditor5": "47.4.0",

View File

@@ -25,8 +25,8 @@
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "5.0.1",
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/eslint-plugin": "8.57.0",
"@typescript-eslint/parser": "8.57.0",
"@vitest/browser": "4.0.18",
"@vitest/coverage-istanbul": "4.0.18",
"ckeditor5": "47.4.0",

View File

@@ -27,8 +27,8 @@
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "5.0.1",
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/eslint-plugin": "8.57.0",
"@typescript-eslint/parser": "8.57.0",
"@vitest/browser": "4.0.18",
"@vitest/coverage-istanbul": "4.0.18",
"ckeditor5": "47.4.0",

View File

@@ -27,8 +27,8 @@
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "5.0.1",
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/eslint-plugin": "8.57.0",
"@typescript-eslint/parser": "8.57.0",
"@vitest/browser": "4.0.18",
"@vitest/coverage-istanbul": "4.0.18",
"ckeditor5": "47.4.0",

View File

@@ -27,8 +27,8 @@
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "5.0.1",
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/eslint-plugin": "8.57.0",
"@typescript-eslint/parser": "8.57.0",
"@vitest/browser": "4.0.18",
"@vitest/coverage-istanbul": "4.0.18",
"ckeditor5": "47.4.0",

View File

@@ -11,6 +11,7 @@ export type { EditorConfig, MentionFeed, MentionFeedObjectItem, ModelNode, Model
export type { TemplateDefinition } from "ckeditor5-premium-features";
export { default as buildExtraCommands } from "./extra_slash_commands.js";
export { default as getCkLocale } from "./i18n.js";
export * from "./utils.js";
// Import with sideffects to ensure that type augmentations are present.
import "@triliumnext/ckeditor5-math";

View File

@@ -0,0 +1,28 @@
import type { DifferItemAttribute, Editor, ModelDocumentFragment, ModelElement, ModelNode } from "ckeditor5";
function hasHeadingAncestor(node: ModelElement | ModelNode | ModelDocumentFragment | null): boolean {
let current: ModelElement | ModelNode | ModelDocumentFragment | null = node;
while (current) {
if (!!current && current.is('element') && (current as ModelElement).name.startsWith("heading")) return true;
current = current.parent;
}
return false;
}
export function attributeChangeAffectsHeading(change: DifferItemAttribute, editor: Editor): boolean {
if (change.type !== "attribute") return false;
// Fast checks on range boundaries
if (hasHeadingAncestor(change.range.start.parent) || hasHeadingAncestor(change.range.end.parent)) {
return true;
}
// Robust check across the whole changed range
const range = editor.model.createRange(change.range.start, change.range.end);
for (const item of range.getItems()) {
const baseNode = item.is("$textProxy") ? item.parent : item;
if (hasHeadingAncestor(baseNode)) return true;
}
return false;
}

View File

@@ -31,8 +31,8 @@
"devDependencies": {
"@digitak/esrun": "3.2.26",
"@triliumnext/ckeditor5": "workspace:*",
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/eslint-plugin": "8.57.0",
"@typescript-eslint/parser": "8.57.0",
"dotenv": "17.3.1",
"esbuild": "0.27.3",
"eslint": "10.0.3",

312
pnpm-lock.yaml generated
View File

@@ -138,8 +138,8 @@ importers:
specifier: 5.9.3
version: 5.9.3
typescript-eslint:
specifier: 8.56.1
version: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
upath:
specifier: 2.0.1
version: 2.0.1
@@ -210,8 +210,8 @@ importers:
specifier: 0.1.3
version: 0.1.3(@types/leaflet@1.9.21)(leaflet@1.9.4)(maplibre-gl@5.6.1)
'@mermaid-js/layout-elk':
specifier: 0.2.0
version: 0.2.0(mermaid@11.12.3)
specifier: 0.2.1
version: 0.2.1(mermaid@11.12.3)
'@mind-elixir/node-menu':
specifier: 5.0.1
version: 5.0.1(mind-elixir@5.9.2)
@@ -731,8 +731,8 @@ importers:
specifier: 2.19.4
version: 2.19.4(express@5.2.1)
express-rate-limit:
specifier: 8.3.0
version: 8.3.0(express@5.2.1)
specifier: 8.3.1
version: 8.3.1(express@5.2.1)
express-session:
specifier: 1.19.0
version: 1.19.0
@@ -959,11 +959,11 @@ importers:
specifier: 5.0.1
version: 5.0.1(@babel/core@7.28.0)(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.12.0)(bufferutil@4.0.9)(esbuild@0.27.3)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: 8.56.1
version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: 8.56.1
version: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.18
version: 4.0.18(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.0)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.31.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18)
@@ -1019,11 +1019,11 @@ importers:
specifier: 5.0.1
version: 5.0.1(@babel/core@7.28.0)(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.12.0)(bufferutil@4.0.9)(esbuild@0.27.3)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: 8.56.1
version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: 8.56.1
version: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.18
version: 4.0.18(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.0)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.31.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18)
@@ -1079,11 +1079,11 @@ importers:
specifier: 5.0.1
version: 5.0.1(@babel/core@7.28.0)(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.12.0)(bufferutil@4.0.9)(esbuild@0.27.3)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: 8.56.1
version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: 8.56.1
version: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.18
version: 4.0.18(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.0)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.31.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18)
@@ -1146,11 +1146,11 @@ importers:
specifier: 5.0.1
version: 5.0.1(@babel/core@7.28.0)(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.12.0)(bufferutil@4.0.9)(esbuild@0.27.3)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: 8.56.1
version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: 8.56.1
version: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.18
version: 4.0.18(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.0)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.31.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18)
@@ -1213,11 +1213,11 @@ importers:
specifier: 5.0.1
version: 5.0.1(@babel/core@7.28.0)(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.12.0)(bufferutil@4.0.9)(esbuild@0.27.3)(utf-8-validate@6.0.5)
'@typescript-eslint/eslint-plugin':
specifier: 8.56.1
version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: 8.56.1
version: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.18
version: 4.0.18(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.12.0)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.31.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18)
@@ -1464,11 +1464,11 @@ importers:
specifier: workspace:*
version: link:../ckeditor5
'@typescript-eslint/eslint-plugin':
specifier: 8.56.1
version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: 8.56.1
version: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
specifier: 8.57.0
version: 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
dotenv:
specifier: 17.3.1
version: 17.3.1
@@ -4032,8 +4032,8 @@ packages:
'@mdn/browser-compat-data@5.7.6':
resolution: {integrity: sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==}
'@mermaid-js/layout-elk@0.2.0':
resolution: {integrity: sha512-vjjYGnCCjYlIA/rR7M//eFi0rHM6dsMyN1JQKfckpt30DTC/esrw36hcrvA2FNPHaqh3Q/SyBWzddyaky8EtUQ==}
'@mermaid-js/layout-elk@0.2.1':
resolution: {integrity: sha512-MX9jwhMyd5zDcFsYcl3duDUkKhjVRUCGEQrdCeNV5hCIR6+3FuDDbRbFmvVbAu15K1+juzsYGG+K8MDvCY1Amg==}
peerDependencies:
mermaid: 11.12.3
@@ -6456,11 +6456,11 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/eslint-plugin@8.56.1':
resolution: {integrity: sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==}
'@typescript-eslint/eslint-plugin@8.57.0':
resolution: {integrity: sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.56.1
'@typescript-eslint/parser': ^8.57.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.0.0'
@@ -6471,8 +6471,8 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/parser@8.56.1':
resolution: {integrity: sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==}
'@typescript-eslint/parser@8.57.0':
resolution: {integrity: sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
@@ -6484,14 +6484,14 @@ packages:
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/project-service@8.56.0':
resolution: {integrity: sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==}
'@typescript-eslint/project-service@8.56.1':
resolution: {integrity: sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/project-service@8.56.1':
resolution: {integrity: sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==}
'@typescript-eslint/project-service@8.57.0':
resolution: {integrity: sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
@@ -6500,28 +6500,28 @@ packages:
resolution: {integrity: sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/scope-manager@8.56.0':
resolution: {integrity: sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/scope-manager@8.56.1':
resolution: {integrity: sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/scope-manager@8.57.0':
resolution: {integrity: sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.46.4':
resolution: {integrity: sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/tsconfig-utils@8.56.0':
resolution: {integrity: sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==}
'@typescript-eslint/tsconfig-utils@8.56.1':
resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/tsconfig-utils@8.56.1':
resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==}
'@typescript-eslint/tsconfig-utils@8.57.0':
resolution: {integrity: sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
@@ -6533,8 +6533,8 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/type-utils@8.56.1':
resolution: {integrity: sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==}
'@typescript-eslint/type-utils@8.57.0':
resolution: {integrity: sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
@@ -6544,28 +6544,28 @@ packages:
resolution: {integrity: sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/types@8.56.0':
resolution: {integrity: sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/types@8.56.1':
resolution: {integrity: sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/types@8.57.0':
resolution: {integrity: sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.46.4':
resolution: {integrity: sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/typescript-estree@8.56.0':
resolution: {integrity: sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==}
'@typescript-eslint/typescript-estree@8.56.1':
resolution: {integrity: sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/typescript-estree@8.56.1':
resolution: {integrity: sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==}
'@typescript-eslint/typescript-estree@8.57.0':
resolution: {integrity: sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
@@ -6577,15 +6577,15 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/utils@8.56.0':
resolution: {integrity: sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==}
'@typescript-eslint/utils@8.56.1':
resolution: {integrity: sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/utils@8.56.1':
resolution: {integrity: sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==}
'@typescript-eslint/utils@8.57.0':
resolution: {integrity: sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
@@ -6595,14 +6595,14 @@ packages:
resolution: {integrity: sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.56.0':
resolution: {integrity: sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.56.1':
resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.57.0':
resolution: {integrity: sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
@@ -9721,8 +9721,8 @@ packages:
peerDependencies:
express: '>= 4.17.0'
express-rate-limit@8.3.0:
resolution: {integrity: sha512-KJzBawY6fB9FiZGdE/0aftepZ91YlaGIrV8vgblRM3J8X+dHx/aiowJWwkx6LIGyuqGiANsjSwwrbb8mifOJ4Q==}
express-rate-limit@8.3.1:
resolution: {integrity: sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==}
engines: {node: '>= 16'}
peerDependencies:
express: '>= 4.11'
@@ -15515,8 +15515,8 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
typescript-eslint@8.56.1:
resolution: {integrity: sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==}
typescript-eslint@8.57.0:
resolution: {integrity: sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
@@ -17287,8 +17287,6 @@ snapshots:
'@ckeditor/ckeditor5-core': 47.4.0
'@ckeditor/ckeditor5-utils': 47.4.0
ckeditor5: 47.4.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-code-block@47.4.0(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)':
dependencies:
@@ -17354,6 +17352,8 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.4.0
'@ckeditor/ckeditor5-watchdog': 47.4.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-dev-build-tools@54.3.3(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)':
dependencies:
@@ -17479,8 +17479,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.4.0
ckeditor5: 47.4.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-classic@47.4.0':
dependencies:
@@ -17490,8 +17488,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.4.0
ckeditor5: 47.4.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-decoupled@47.4.0':
dependencies:
@@ -17510,8 +17506,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.4.0
ckeditor5: 47.4.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-multi-root@47.4.0':
dependencies:
@@ -17692,8 +17686,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.4.0
'@ckeditor/ckeditor5-widget': 47.4.0
ckeditor5: 47.4.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-html-embed@47.4.0':
dependencies:
@@ -18023,8 +18015,6 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.4.0
'@ckeditor/ckeditor5-utils': 47.4.0
ckeditor5: 47.4.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-restricted-editing@47.4.0':
dependencies:
@@ -18111,8 +18101,6 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.4.0
'@ckeditor/ckeditor5-utils': 47.4.0
ckeditor5: 47.4.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-special-characters@47.4.0':
dependencies:
@@ -18968,7 +18956,7 @@ snapshots:
'@es-joy/jsdoccomment@0.50.2':
dependencies:
'@types/estree': 1.0.8
'@typescript-eslint/types': 8.56.0
'@typescript-eslint/types': 8.56.1
comment-parser: 1.4.1
esquery: 1.7.0
jsdoc-type-pratt-parser: 4.1.0
@@ -20332,7 +20320,7 @@ snapshots:
'@mdn/browser-compat-data@5.7.6': {}
'@mermaid-js/layout-elk@0.2.0(mermaid@11.12.3)':
'@mermaid-js/layout-elk@0.2.1(mermaid@11.12.3)':
dependencies:
d3: 7.9.0
elkjs: 0.9.3
@@ -22286,7 +22274,7 @@ snapshots:
'@stylistic/eslint-plugin@4.4.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/utils': 8.56.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
eslint: 10.0.3(jiti@2.6.1)
eslint-visitor-keys: 4.2.1
espree: 10.4.0
@@ -22993,14 +22981,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/eslint-plugin@8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.56.1
'@typescript-eslint/type-utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.56.1
'@typescript-eslint/parser': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.57.0
'@typescript-eslint/type-utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.57.0
eslint: 10.0.3(jiti@2.6.1)
ignore: 7.0.5
natural-compare: 1.4.0
@@ -23021,12 +23009,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.56.1
'@typescript-eslint/types': 8.56.1
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.56.1
'@typescript-eslint/scope-manager': 8.57.0
'@typescript-eslint/types': 8.57.0
'@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.57.0
debug: 4.4.3(supports-color@8.1.1)
eslint: 10.0.3(jiti@2.6.1)
typescript: 5.9.3
@@ -23035,17 +23023,8 @@ snapshots:
'@typescript-eslint/project-service@8.46.4(typescript@5.9.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.56.0(typescript@5.9.3)
'@typescript-eslint/types': 8.56.0
debug: 4.4.3(supports-color@8.1.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.56.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.56.0(typescript@5.9.3)
'@typescript-eslint/types': 8.56.0
'@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3)
'@typescript-eslint/types': 8.56.1
debug: 4.4.3(supports-color@8.1.1)
typescript: 5.9.3
transitivePeerDependencies:
@@ -23060,30 +23039,39 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.57.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.57.0(typescript@5.9.3)
'@typescript-eslint/types': 8.57.0
debug: 4.4.3(supports-color@8.1.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@8.46.4':
dependencies:
'@typescript-eslint/types': 8.46.4
'@typescript-eslint/visitor-keys': 8.46.4
'@typescript-eslint/scope-manager@8.56.0':
dependencies:
'@typescript-eslint/types': 8.56.0
'@typescript-eslint/visitor-keys': 8.56.0
'@typescript-eslint/scope-manager@8.56.1':
dependencies:
'@typescript-eslint/types': 8.56.1
'@typescript-eslint/visitor-keys': 8.56.1
'@typescript-eslint/scope-manager@8.57.0':
dependencies:
'@typescript-eslint/types': 8.57.0
'@typescript-eslint/visitor-keys': 8.57.0
'@typescript-eslint/tsconfig-utils@8.46.4(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
'@typescript-eslint/tsconfig-utils@8.56.0(typescript@5.9.3)':
'@typescript-eslint/tsconfig-utils@8.56.1(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
'@typescript-eslint/tsconfig-utils@8.56.1(typescript@5.9.3)':
'@typescript-eslint/tsconfig-utils@8.57.0(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
@@ -23099,11 +23087,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/type-utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/type-utils@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.56.1
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
'@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/types': 8.57.0
'@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.3(supports-color@8.1.1)
eslint: 10.0.3(jiti@2.6.1)
ts-api-utils: 2.4.0(typescript@5.9.3)
@@ -23113,10 +23101,10 @@ snapshots:
'@typescript-eslint/types@8.46.4': {}
'@typescript-eslint/types@8.56.0': {}
'@typescript-eslint/types@8.56.1': {}
'@typescript-eslint/types@8.57.0': {}
'@typescript-eslint/typescript-estree@8.46.4(typescript@5.9.3)':
dependencies:
'@typescript-eslint/project-service': 8.46.4(typescript@5.9.3)
@@ -23133,21 +23121,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.56.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/project-service': 8.56.0(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.56.0(typescript@5.9.3)
'@typescript-eslint/types': 8.56.0
'@typescript-eslint/visitor-keys': 8.56.0
debug: 4.4.3(supports-color@8.1.1)
minimatch: 9.0.5
semver: 7.7.3
tinyglobby: 0.2.15
ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3)':
dependencies:
'@typescript-eslint/project-service': 8.56.1(typescript@5.9.3)
@@ -23155,7 +23128,22 @@ snapshots:
'@typescript-eslint/types': 8.56.1
'@typescript-eslint/visitor-keys': 8.56.1
debug: 4.4.3(supports-color@8.1.1)
minimatch: 10.2.2
minimatch: 10.2.4
semver: 7.7.3
tinyglobby: 0.2.15
ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.57.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/project-service': 8.57.0(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.57.0(typescript@5.9.3)
'@typescript-eslint/types': 8.57.0
'@typescript-eslint/visitor-keys': 8.57.0
debug: 4.4.3(supports-color@8.1.1)
minimatch: 10.2.4
semver: 7.7.3
tinyglobby: 0.2.15
ts-api-utils: 2.4.0(typescript@5.9.3)
@@ -23174,17 +23162,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.56.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.56.0
'@typescript-eslint/types': 8.56.0
'@typescript-eslint/typescript-estree': 8.56.0(typescript@5.9.3)
eslint: 10.0.3(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1))
@@ -23196,21 +23173,32 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.57.0
'@typescript-eslint/types': 8.57.0
'@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3)
eslint: 10.0.3(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@8.46.4':
dependencies:
'@typescript-eslint/types': 8.46.4
eslint-visitor-keys: 4.2.1
'@typescript-eslint/visitor-keys@8.56.0':
dependencies:
'@typescript-eslint/types': 8.56.0
eslint-visitor-keys: 5.0.1
'@typescript-eslint/visitor-keys@8.56.1':
dependencies:
'@typescript-eslint/types': 8.56.1
eslint-visitor-keys: 5.0.1
'@typescript-eslint/visitor-keys@8.57.0':
dependencies:
'@typescript-eslint/types': 8.57.0
eslint-visitor-keys: 5.0.1
'@ungap/structured-clone@1.3.0': {}
'@univerjs-pro/collaboration-client-ui@0.16.1(@types/react-dom@19.1.6(@types/react@19.1.7))(@types/react@19.1.7)(@wendellhu/redi@1.1.1(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)':
@@ -28017,7 +28005,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
express-rate-limit@8.3.0(express@5.2.1):
express-rate-limit@8.3.1(express@5.2.1):
dependencies:
express: 5.2.1
ip-address: 10.1.0
@@ -29229,7 +29217,7 @@ snapshots:
ignore-walk@8.0.0:
dependencies:
minimatch: 10.2.2
minimatch: 10.2.4
ignore@5.3.2: {}
@@ -35001,12 +34989,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
typescript-eslint@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3):
typescript-eslint@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
'@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/eslint-plugin': 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.57.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)
eslint: 10.0.3(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies: