From 565989dd4c36a1b17f16f6d4a4d7f62bb2255ebe Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 28 Jan 2025 15:44:15 +0200 Subject: [PATCH 1/5] feat(client/ts): port tree (WIP) --- package-lock.json | 22 +- package.json | 1 + src/public/app/components/app_context.ts | 25 +- src/public/app/components/component.ts | 2 +- src/public/app/entities/fbranch.ts | 1 + src/public/app/menus/launcher_context_menu.ts | 8 +- src/public/app/menus/tree_context_menu.ts | 8 +- src/public/app/services/import.ts | 13 +- src/public/app/services/tree.ts | 18 +- src/public/app/services/utils.ts | 2 +- src/public/app/types.d.ts | 2 +- .../app/widgets/note_context_aware_widget.ts | 2 +- .../widgets/{note_tree.js => note_tree.ts} | 284 ++++++++++-------- src/services/special_notes.ts | 2 +- 14 files changed, 232 insertions(+), 158 deletions(-) rename src/public/app/widgets/{note_tree.js => note_tree.ts} (85%) diff --git a/package-lock.json b/package-lock.json index 558711182..129869265 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@mermaid-js/layout-elk": "0.1.7", "@mind-elixir/node-menu": "1.0.4", "@triliumnext/express-partial-content": "1.0.1", + "@types/jquery.fancytree": "0.0.11", "@types/leaflet": "1.9.16", "@types/react-dom": "18.3.5", "archiver": "7.0.1", @@ -3788,12 +3789,30 @@ "version": "3.5.32", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.32.tgz", "integrity": "sha512-b9Xbf4CkMqS02YH8zACqN1xzdxc3cO735Qe5AbSUFmyOiaWAbcpqh9Wna+Uk0vgACvoQHpWDg2rGdHkYPLmCiQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/sizzle": "*" } }, + "node_modules/@types/jquery.fancytree": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@types/jquery.fancytree/-/jquery.fancytree-0.0.11.tgz", + "integrity": "sha512-ga0wwAa8SLSAxdg+kU6wH8PMY/XxWx+rOzzQz4z1t1GSj/9suYakgQhcAT2gVk6yBdzYHT8ltpkhfCxhEtk0Rg==", + "license": "MIT", + "dependencies": { + "@types/jquery": "*", + "@types/jqueryui": "*" + } + }, + "node_modules/@types/jqueryui": { + "version": "1.12.23", + "resolved": "https://registry.npmjs.org/@types/jqueryui/-/jqueryui-1.12.23.tgz", + "integrity": "sha512-pm1yVNVI29B9IGw41anCEzA5eR2r1pYc7flqD471ZT7B0yUXIY7YNe/zq7LGpihIGXNzWyG+Q4YQSzv2AF3fNA==", + "license": "MIT", + "dependencies": { + "@types/jquery": "*" + } + }, "node_modules/@types/jsdom": { "version": "21.1.7", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", @@ -4046,7 +4065,6 @@ "version": "2.3.9", "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz", "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==", - "dev": true, "license": "MIT" }, "node_modules/@types/source-map-support": { diff --git a/package.json b/package.json index d404ad638..88922a22e 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@mermaid-js/layout-elk": "0.1.7", "@mind-elixir/node-menu": "1.0.4", "@triliumnext/express-partial-content": "1.0.1", + "@types/jquery.fancytree": "0.0.11", "@types/leaflet": "1.9.16", "@types/react-dom": "18.3.5", "archiver": "7.0.1", diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index 072977695..45f7f5985 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -18,7 +18,6 @@ import type NoteDetailWidget from "../widgets/note_detail.js"; import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js"; import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js"; import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js"; -import type { Node } from "../services/tree.js"; import type LoadResults from "../services/load_results.js"; import type { Attribute } from "../services/attribute_parser.js"; import type NoteTreeWidget from "../widgets/note_tree.js"; @@ -48,10 +47,10 @@ export interface CommandData { * Represents a set of commands that are triggered from the context menu, providing information such as the selected note. */ export interface ContextMenuCommandData extends CommandData { - node: Node; - notePath: string; + node: Fancytree.FancytreeNode; + notePath?: string; noteId?: string; - selectedOrActiveBranchIds: any; // TODO: Remove any once type is defined + selectedOrActiveBranchIds?: any; // TODO: Remove any once type is defined selectedOrActiveNoteIds: any; // TODO: Remove any once type is defined } @@ -71,6 +70,7 @@ export interface ExecuteCommandData extends CommandData { export type CommandMappings = { "api-log-messages": CommandData; focusTree: CommandData, + focusOnTitle: CommandData; focusOnDetail: CommandData; focusOnSearchDefinition: Required; searchNotes: CommandData & { @@ -99,6 +99,12 @@ export type CommandMappings = { showPromptDialog: PromptDialogOptions; showInfoDialog: ConfirmWithMessageOptions; showConfirmDialog: ConfirmWithMessageOptions; + showRecentChanges: CommandData & { ancestorNoteId: string }; + showExportDialog: CommandData & { + notePath: string; + defaultType: "subtree" + }; + showImportDialog: CommandData & { noteId: string; }; openNewNoteSplit: NoteCommandData; openInWindow: NoteCommandData; openNoteInNewTab: CommandData; @@ -106,6 +112,7 @@ export type CommandMappings = { openNoteInNewWindow: CommandData; hideLeftPane: CommandData; showLeftPane: CommandData; + hoistNote: CommandData & { noteId: string }; openInTab: ContextMenuCommandData; openNoteInSplit: ContextMenuCommandData; @@ -113,9 +120,12 @@ export type CommandMappings = { insertNoteAfter: ContextMenuCommandData; insertChildNote: ContextMenuCommandData; delete: ContextMenuCommandData; + editNoteTitle: ContextMenuCommandData; protectSubtree: ContextMenuCommandData; unprotectSubtree: ContextMenuCommandData; - openBulkActionsDialog: ContextMenuCommandData; + openBulkActionsDialog: ContextMenuCommandData | { + selectedOrActiveNoteIds: string[] + }; editBranchPrefix: ContextMenuCommandData; convertNoteToAttachment: ContextMenuCommandData; duplicateSubtree: ContextMenuCommandData; @@ -134,6 +144,11 @@ export type CommandMappings = { importIntoNote: ContextMenuCommandData; exportNote: ContextMenuCommandData; searchInSubtree: ContextMenuCommandData; + moveNoteUp: ContextMenuCommandData; + moveNoteDown: ContextMenuCommandData; + moveNoteUpInHierarchy: ContextMenuCommandData; + moveNoteDownInHierarchy: ContextMenuCommandData; + selectAllNotesInParent: ContextMenuCommandData; addNoteLauncher: ContextMenuCommandData; addScriptLauncher: ContextMenuCommandData; diff --git a/src/public/app/components/component.ts b/src/public/app/components/component.ts index 0ab812bbf..ad35e911d 100644 --- a/src/public/app/components/component.ts +++ b/src/public/app/components/component.ts @@ -80,7 +80,7 @@ export class TypedComponent> { return promises.length > 0 ? Promise.all(promises) : null; } - triggerCommand(name: string, _data?: CommandMappings[K]): Promise | undefined | null { + triggerCommand(name: K, _data?: CommandMappings[K]): Promise | undefined | null { const data = _data || {}; const fun = (this as any)[`${name}Command`]; diff --git a/src/public/app/entities/fbranch.ts b/src/public/app/entities/fbranch.ts index f63401b2d..7a5cde4f8 100644 --- a/src/public/app/entities/fbranch.ts +++ b/src/public/app/entities/fbranch.ts @@ -8,6 +8,7 @@ export interface FBranchRow { prefix?: string; isExpanded?: boolean; fromSearchNote: boolean; + isDeleted?: boolean; } /** diff --git a/src/public/app/menus/launcher_context_menu.ts b/src/public/app/menus/launcher_context_menu.ts index 3c4fb68f3..bc219e591 100644 --- a/src/public/app/menus/launcher_context_menu.ts +++ b/src/public/app/menus/launcher_context_menu.ts @@ -1,4 +1,4 @@ -import treeService, { type Node } from "../services/tree.js"; +import treeService from "../services/tree.js"; import froca from "../services/froca.js"; import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js"; import dialogService from "../services/dialog.js"; @@ -12,14 +12,14 @@ type LauncherCommandNames = FilteredCommandNames; export default class LauncherContextMenu implements SelectMenuItemEventListener { private treeWidget: NoteTreeWidget; - private node: Node; + private node: Fancytree.FancytreeNode; - constructor(treeWidget: NoteTreeWidget, node: Node) { + constructor(treeWidget: NoteTreeWidget, node: Fancytree.FancytreeNode) { this.treeWidget = treeWidget; this.node = node; } - async show(e: PointerEvent) { + async show(e: PointerEvent | JQuery.TouchStartEvent | JQuery.ContextMenuEvent) { contextMenu.show({ x: e.pageX, y: e.pageY, diff --git a/src/public/app/menus/tree_context_menu.ts b/src/public/app/menus/tree_context_menu.ts index 650432828..74b933d4a 100644 --- a/src/public/app/menus/tree_context_menu.ts +++ b/src/public/app/menus/tree_context_menu.ts @@ -1,4 +1,4 @@ -import treeService, { type Node } from "../services/tree.js"; +import treeService from "../services/tree.js"; import froca from "../services/froca.js"; import clipboard from "../services/clipboard.js"; import noteCreateService from "../services/note_create.js"; @@ -22,14 +22,14 @@ type TreeCommandNames = FilteredCommandNames; export default class TreeContextMenu implements SelectMenuItemEventListener { private treeWidget: NoteTreeWidget; - private node: Node; + private node: Fancytree.FancytreeNode; - constructor(treeWidget: NoteTreeWidget, node: Node) { + constructor(treeWidget: NoteTreeWidget, node: Fancytree.FancytreeNode) { this.treeWidget = treeWidget; this.node = node; } - async show(e: PointerEvent) { + async show(e: PointerEvent | JQuery.TouchStartEvent | JQuery.ContextMenuEvent) { contextMenu.show({ x: e.pageX, y: e.pageY, diff --git a/src/public/app/services/import.ts b/src/public/app/services/import.ts index 9f06807f2..97cc40c94 100644 --- a/src/public/app/services/import.ts +++ b/src/public/app/services/import.ts @@ -5,7 +5,16 @@ import utils from "./utils.js"; import appContext from "../components/app_context.js"; import { t } from "./i18n.js"; -export async function uploadFiles(entityType: string, parentNoteId: string, files: string[], options: Record) { +interface UploadFilesOptions { + safeImport: boolean; + shrinkImages: boolean; + textImportedAsText: boolean; + codeImportedAsCode: boolean; + explodeArchives: boolean; + replaceUnderscoresWithSpaces: boolean; +} + +export async function uploadFiles(entityType: string, parentNoteId: string, files: string[], options: UploadFilesOptions) { if (!["notes", "attachments"].includes(entityType)) { throw new Error(`Unrecognized import entity type '${entityType}'.`); } @@ -26,7 +35,7 @@ export async function uploadFiles(entityType: string, parentNoteId: string, file formData.append("last", counter === files.length ? "true" : "false"); for (const key in options) { - formData.append(key, options[key]); + formData.append(key, (options as any)[key]); } await $.ajax({ diff --git a/src/public/app/services/tree.ts b/src/public/app/services/tree.ts index 0a56771a4..e7c94ca0e 100644 --- a/src/public/app/services/tree.ts +++ b/src/public/app/services/tree.ts @@ -4,20 +4,6 @@ import froca from "./froca.js"; import hoistedNoteService from "../services/hoisted_note.js"; import appContext from "../components/app_context.js"; -export interface Node { - title: string; - getParent(): Node; - getChildren(): Node[]; - folder: boolean; - renderTitle(): void; - data: { - noteId?: string; - isProtected?: boolean; - branchId: string; - noteType: string; - }; -} - /** * @returns {string|null} */ @@ -148,7 +134,7 @@ ws.subscribeToMessages((message) => { } }); -function getParentProtectedStatus(node: Node) { +function getParentProtectedStatus(node: Fancytree.FancytreeNode) { return hoistedNoteService.isHoistedNode(node) ? false : node.getParent().data.isProtected; } @@ -205,7 +191,7 @@ function getNoteIdAndParentIdFromUrl(urlOrNotePath: string) { }; } -function getNotePath(node: Node) { +function getNotePath(node: Fancytree.FancytreeNode) { if (!node) { logError("Node is null"); return ""; diff --git a/src/public/app/services/utils.ts b/src/public/app/services/utils.ts index 7c7e47b31..cea439b7f 100644 --- a/src/public/app/services/utils.ts +++ b/src/public/app/services/utils.ts @@ -101,7 +101,7 @@ function isCtrlKey(evt: KeyboardEvent | MouseEvent | JQuery.ClickEvent | JQuery. return (!isMac() && evt.ctrlKey) || (isMac() && evt.metaKey); } -function assertArguments(...args: string[]) { +function assertArguments(...args: T[]) { for (const i in args) { if (!args[i]) { console.trace(`Argument idx#${i} should not be falsy: ${args[i]}`); diff --git a/src/public/app/types.d.ts b/src/public/app/types.d.ts index b1750afb4..974d4d129 100644 --- a/src/public/app/types.d.ts +++ b/src/public/app/types.d.ts @@ -106,7 +106,7 @@ declare global { } } - var logError: (message: string, e?: Error) => void; + var logError: (message: string, e?: Error | string) => void; var logInfo: (message: string) => void; var glob: CustomGlobals; var require: RequireMethod; diff --git a/src/public/app/widgets/note_context_aware_widget.ts b/src/public/app/widgets/note_context_aware_widget.ts index 9f9d2448b..3c1153c2f 100644 --- a/src/public/app/widgets/note_context_aware_widget.ts +++ b/src/public/app/widgets/note_context_aware_widget.ts @@ -125,7 +125,7 @@ class NoteContextAwareWidget extends BasicWidget { } } - async frocaReloadedEvent() { + async frocaReloadedEvent(): Promise { await this.refresh(); } } diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.ts similarity index 85% rename from src/public/app/widgets/note_tree.js rename to src/public/app/widgets/note_tree.ts index 4afe57117..da5a7914f 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.ts @@ -9,7 +9,7 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js"; import server from "../services/server.js"; import noteCreateService from "../services/note_create.js"; import toastService from "../services/toast.js"; -import appContext from "../components/app_context.js"; +import appContext, { type CommandData, type CommandListenerData, type EventData } from "../components/app_context.js"; import keyboardActionsService from "../services/keyboard_actions.js"; import clipboard from "../services/clipboard.js"; import protectedSessionService from "../services/protected_session.js"; @@ -19,6 +19,13 @@ import protectedSessionHolder from "../services/protected_session_holder.js"; import dialogService from "../services/dialog.js"; import shortcutService from "../services/shortcuts.js"; import { t } from "../services/i18n.js"; +import type FBranch from "../entities/fbranch.js"; +import type LoadResults from "../services/load_results.js"; +import type FNote from "../entities/fnote.js"; +import type { NoteType } from "../entities/fnote.js"; +import type { FBranchRow } from "../entities/fbranch.js"; +import type { BranchRow, NoteRow } from "../../../becca/entities/rows.js"; +import type { AttributeRow } from "../services/load_results.js"; const TPL = `
@@ -141,9 +148,54 @@ const TPL = ` const MAX_SEARCH_RESULTS_IN_TREE = 100; // this has to be hanged on the actual elements to effectively intercept and stop click event -const cancelClickPropagation = (e) => e.stopPropagation(); +const cancelClickPropagation: JQuery.TypeEventHandler = (e) => e.stopPropagation(); + +// TODO: Fix once we remove Node.js API from public +type Timeout = NodeJS.Timeout | string | number | undefined; + +// TODO: Deduplicate with server special_notes +type LauncherType = "launcher" | "note" | "script" | "customWidget" | "spacer"; + +// TODO: Deduplicate with the server +interface CreateLauncherResponse { + success: boolean; + message: string; + note: { + noteId: string; + } +} + +interface ExpandedSubtreeResponse { + branchIds: string[] +} + +interface Node extends Fancytree.NodeData { + noteId: string; + parentNoteId: string; + branchId: string; + isProtected: boolean; + noteType: NoteType; +} + +interface RefreshContext { + noteIdstoUpdate: Set; + noteIdsToReload: Set; +} export default class NoteTreeWidget extends NoteContextAwareWidget { + + private $tree!: JQuery; + private $treeActions!: JQuery; + private $treeSettingsButton!: JQuery; + private $treeSettingsPopup!: JQuery; + private $saveTreeSettingsButton!: JQuery; + private $hideArchivedNotesCheckbox!: JQuery; + private $autoCollapseNoteTree!: JQuery; + private treeName: "main"; + private autoCollapseTimeoutId?: Timeout; + private lastFilteredHoistedNotePath?: string | null; + private tree!: Fancytree.Fancytree; + constructor() { super(); @@ -158,7 +210,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { this.$tree.on("mousedown", ".unhoist-button", () => hoistedNoteService.unhoist()); this.$tree.on("mousedown", ".refresh-search-button", (e) => this.refreshSearch(e)); this.$tree.on("mousedown", ".add-note-button", (e) => { - const node = $.ui.fancytree.getNode(e); + const node = $.ui.fancytree.getNode(e as unknown as Event); const parentNotePath = treeService.getNotePath(node); noteCreateService.createNote(parentNotePath, { @@ -167,7 +219,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { }); this.$tree.on("mousedown", ".enter-workspace-button", (e) => { - const node = $.ui.fancytree.getNode(e); + const node = $.ui.fancytree.getNode(e as unknown as Event); this.triggerCommand("hoistNote", { noteId: node.data.noteId }); }); @@ -175,7 +227,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { // fancytree doesn't support middle click, so this is a way to support it this.$tree.on("mousedown", ".fancytree-title", (e) => { if (e.which === 2) { - const node = $.ui.fancytree.getNode(e); + const node = $.ui.fancytree.getNode(e as unknown as Event); const notePath = treeService.getNotePath(node); @@ -202,8 +254,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { this.$hideArchivedNotesCheckbox.prop("checked", this.hideArchivedNotes); this.$autoCollapseNoteTree.prop("checked", this.autoCollapseNoteTree); - const top = this.$treeActions[0].offsetTop - this.$treeSettingsPopup.outerHeight(); - const left = Math.max(0, this.$treeActions[0].offsetLeft - this.$treeSettingsPopup.outerWidth() + this.$treeActions.outerWidth()); + const top = this.$treeActions[0].offsetTop - (this.$treeSettingsPopup.outerHeight() ?? 0); + const left = Math.max(0, this.$treeActions[0].offsetLeft - (this.$treeSettingsPopup.outerWidth() ?? 0) + (this.$treeActions.outerWidth() ?? 0)); this.$treeSettingsPopup .css({ @@ -243,16 +295,19 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { // see https://github.com/zadam/trilium/pull/1120 for discussion // code inspired by https://gist.github.com/jtsternberg/c272d7de5b967cec2d3d - const isEnclosing = ($container, $sub) => { + const isEnclosing = ($container: JQuery, $sub: JQuery) => { const conOffset = $container.offset(); - const conDistanceFromTop = conOffset.top + $container.outerHeight(true); - const conDistanceFromLeft = conOffset.left + $container.outerWidth(true); + const conDistanceFromTop = (conOffset?.top ?? 0) + ($container.outerHeight(true) ?? 0); + const conDistanceFromLeft = (conOffset?.left ?? 0) + ($container.outerWidth(true) ?? 0); const subOffset = $sub.offset(); - const subDistanceFromTop = subOffset.top + $sub.outerHeight(true); - const subDistanceFromLeft = subOffset.left + $sub.outerWidth(true); + const subDistanceFromTop = (subOffset?.top ?? 0) + ($sub.outerHeight(true) ?? 0); + const subDistanceFromLeft = (subOffset?.left ?? 0) + ($sub.outerWidth(true) ?? 0); - return conDistanceFromTop > subDistanceFromTop && conOffset.top < subOffset.top && conDistanceFromLeft > subDistanceFromLeft && conOffset.left < subOffset.left; + return conDistanceFromTop > subDistanceFromTop + && (conOffset?.top ?? 0) < (subOffset?.top ?? 0) + && conDistanceFromLeft > subDistanceFromLeft + && (conOffset?.left ?? 0) < (subOffset?.left ?? 0); }; this.$tree.on("mouseenter", "span.fancytree-title", (e) => { @@ -264,7 +319,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return options.is(`hideArchivedNotes_${this.treeName}`); } - async setHideArchivedNotes(val) { + async setHideArchivedNotes(val: string) { await options.save(`hideArchivedNotes_${this.treeName}`, val.toString()); } @@ -272,7 +327,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return options.is("autoCollapseNoteTree"); } - async setAutoCollapseNoteTree(val) { + async setAutoCollapseNoteTree(val: string) { await options.save("autoCollapseNoteTree", val.toString()); } @@ -312,7 +367,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { this.clearSelectedNodes(); - function selectInBetween(first, second) { + function selectInBetween(first: Fancytree.FancytreeNode, second: Fancytree.FancytreeNode) { for (let i = 0; first && first !== second && i < 10000; i++) { first.setSelected(true); first = first.getNextSibling(); @@ -336,7 +391,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { node.setFocus(true); } else if (data.node.isActive()) { // this is important for single column mobile view, otherwise it's not possible to see again previously displayed note - this.tree.reactivate(true); + this.tree.reactivate(); } else { node.setActive(); } @@ -448,7 +503,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { }); } else { const jsonStr = dataTransfer.getData("text"); - let notes = null; + let notes: BranchRow[]; try { notes = JSON.parse(jsonStr); @@ -511,7 +566,10 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { clones: { highlightActiveClones: true }, - enhanceTitle: async function (event, data) { + enhanceTitle: async function (event: Event, data: { + node: Fancytree.FancytreeNode; + noteId: string; + }) { const node = data.node; if (!node.data.noteId) { @@ -595,7 +653,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { const isMobile = utils.isMobile(); if (isMobile) { - let showTimeout; + let showTimeout: Timeout; this.$tree.on("touchstart", ".fancytree-node", (e) => { touchStart = new Date().getTime(); @@ -635,8 +693,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { this.tree = $.ui.fancytree.getTree(this.$tree); } - showContextMenu(e) { - const node = $.ui.fancytree.getNode(e); + showContextMenu(e: PointerEvent | JQuery.TouchStartEvent | JQuery.ContextMenuEvent) { + const node = $.ui.fancytree.getNode(e as unknown as Event); const note = froca.getNoteFromCache(node.data.noteId); if (note.isLaunchBarConfig()) { @@ -653,13 +711,11 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } prepareRootNode() { - return this.prepareNode(froca.getBranch("none_root")); + const branch = froca.getBranch("none_root"); + return branch && this.prepareNode(branch); } - /** - * @param {FNote} parentNote - */ - prepareChildren(parentNote) { + prepareChildren(parentNote: FNote) { utils.assertArguments(parentNote); const noteList = []; @@ -690,7 +746,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return noteList; } - async updateNode(node) { + async updateNode(node: Fancytree.FancytreeNode) { const note = froca.getNoteFromCache(node.data.noteId); const branch = froca.getBranch(node.data.branchId); @@ -718,11 +774,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { node.renderTitle(); } - /** - * @param {FBranch} branch - * @param {boolean} forceLazy - */ - prepareNode(branch, forceLazy = false) { + prepareNode(branch: FBranch, forceLazy = false) { const note = branch.getNoteFromCache(); if (!note) { @@ -734,7 +786,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { const isFolder = note.isFolder(); - const node = { + const node: Node = { noteId: note.noteId, parentNoteId: branch.parentNoteId, branchId: branch.branchId, @@ -742,7 +794,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { noteType: note.type, title: utils.escapeHtml(title), extraClasses: this.getExtraClasses(note), - icon: note.getIcon(isFolder), + icon: note.getIcon(), refKey: note.noteId, lazy: true, folder: isFolder, @@ -757,7 +809,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return node; } - getExtraClasses(note) { + getExtraClasses(note: FNote) { utils.assertArguments(note); const extraClasses = []; @@ -773,9 +825,9 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { if (note.getParentNoteIds().length > 1) { const realClones = note .getParentNoteIds() - .map((noteId) => froca.notes[noteId]) - .filter((note) => !!note) - .filter((note) => !["_share", "_lbBookmarks"].includes(note.noteId) && note.type !== "search"); + .map((noteId: string) => froca.notes[noteId]) + .filter((note: FNote) => !!note) + .filter((note: FNote) => !["_share", "_lbBookmarks"].includes(note.noteId) && note.type !== "search"); if (realClones.length > 1) { extraClasses.push("multiple-parents"); @@ -813,8 +865,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return this.tree.getSelectedNodes(stopOnParents); } - /** @returns {FancytreeNode[]} */ - getSelectedOrActiveNodes(node = null) { + getSelectedOrActiveNodes(node: Fancytree.FancytreeNode | null = null) { const nodes = this.getSelectedNodes(true); // the node you start dragging should be included even if not selected @@ -831,14 +882,14 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return nodes.filter((node) => hoistedNoteService.getHoistedNoteId() !== "root" || node.data.noteId !== "_hidden"); } - async setExpandedStatusForSubtree(node, isExpanded) { + async setExpandedStatusForSubtree(node: Fancytree.FancytreeNode | null, isExpanded: boolean) { if (!node) { const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); node = this.getNodesByNoteId(hoistedNoteId)[0]; } - const { branchIds } = await server.put(`branches/${node.data.branchId}/expanded-subtree/${isExpanded ? 1 : 0}`); + const { branchIds } = await server.put(`branches/${node.data.branchId}/expanded-subtree/${isExpanded ? 1 : 0}`); froca.getBranches(branchIds, true).forEach((branch) => (branch.isExpanded = !!isExpanded)); @@ -856,11 +907,11 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { // don't activate the active note, see discussion in https://github.com/zadam/trilium/issues/3664 } - async expandTree(node = null) { + async expandTree(node: Fancytree.FancytreeNode | null = null) { await this.setExpandedStatusForSubtree(node, true); } - async collapseTree(node = null) { + async collapseTree(node: Fancytree.FancytreeNode | null = null) { await this.setExpandedStatusForSubtree(node, false); } @@ -911,8 +962,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { this.tree.setFocus(true); } - /** @returns {FancytreeNode} */ - async getNodeFromPath(notePath, expand = false, logErrors = true) { + async getNodeFromPath(notePath: string, expand = false, logErrors = true) { utils.assertArguments(notePath); /** @let {FancytreeNode} */ let parentNode = this.getNodesByNoteId("root")[0]; @@ -944,7 +994,9 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { // although the previous line should set the expanded status, it seems to happen asynchronously, // so we need to make sure it is set properly before calling updateNode which uses this flag const branch = froca.getBranch(parentNode.data.branchId); - branch.isExpanded = true; + if (branch) { + branch.isExpanded = true; + } } await this.updateNode(parentNode); @@ -983,25 +1035,21 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return parentNode; } - /** @returns {FancytreeNode} */ - findChildNode(parentNode, childNoteId) { + findChildNode(parentNode: Fancytree.FancytreeNode, childNoteId: string) { return parentNode.getChildren().find((childNode) => childNode.data.noteId === childNoteId); } - /** @returns {FancytreeNode} */ - async expandToNote(notePath, logErrors = true) { + async expandToNote(notePath: string, logErrors = true) { return this.getNodeFromPath(notePath, true, logErrors); } - /** @returns {FancytreeNode[]} */ - getNodesByBranch(branch) { + getNodesByBranch(branch: BranchRow) { utils.assertArguments(branch); return this.getNodesByNoteId(branch.noteId).filter((node) => node.data.branchId === branch.branchId); } - /** @returns {FancytreeNode[]} */ - getNodesByNoteId(noteId) { + getNodesByNoteId(noteId: string) { utils.assertArguments(noteId); const list = this.tree.getNodesByRef(noteId); @@ -1036,7 +1084,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } if (newActiveNode) { - if (!newActiveNode.isVisible()) { + if (!newActiveNode.isVisible() && this.noteContext?.notePath) { await this.expandToNote(this.noteContext.notePath); } @@ -1048,8 +1096,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { this.filterHoistedBranch(false); } - async refreshSearch(e) { - const activeNode = $.ui.fancytree.getNode(e); + async refreshSearch(e: JQuery.MouseDownEvent) { + const activeNode = $.ui.fancytree.getNode(e as unknown as Event); activeNode.load(true); activeNode.setExpanded(true, { noAnimation: true }); @@ -1057,7 +1105,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { toastService.showMessage(t("note_tree.saved-search-note-refreshed")); } - async batchUpdate(cb) { + async batchUpdate(cb: () => Promise) { try { // disable rendering during update for increased performance this.tree.enableUpdate(false); @@ -1108,7 +1156,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { }, 600 * 1000); } - async entitiesReloadedEvent({ loadResults }) { + async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { this.activityDetected(); if (loadResults.isEmptyForTree()) { @@ -1119,7 +1167,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { const activeNodeFocused = activeNode?.hasFocus(); const activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null; - const refreshCtx = { + const refreshCtx: RefreshContext = { noteIdsToUpdate: new Set(), noteIdsToReload: new Set() }; @@ -1142,17 +1190,17 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - #processAttributeRows(attributeRows, refreshCtx) { + #processAttributeRows(attributeRows: AttributeRow[], refreshCtx) { for (const attrRow of attributeRows) { const dirtyingLabels = ["iconClass", "cssClass", "workspace", "workspaceIconClass", "color"]; - if (attrRow.type === "label" && dirtyingLabels.includes(attrRow.name)) { + if (attrRow.type === "label" && dirtyingLabels.includes(attrRow.name ?? "")) { if (attrRow.isInheritable) { refreshCtx.noteIdsToReload.add(attrRow.noteId); } else { refreshCtx.noteIdsToUpdate.add(attrRow.noteId); } - } else if (attrRow.type === "label" && attrRow.name === "archived") { + } else if (attrRow.type === "label" && attrRow.name === "archived" && attrRow.noteId) { const note = froca.getNoteFromCache(attrRow.noteId); if (note) { @@ -1165,10 +1213,10 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } else if (attrRow.type === "relation" && (attrRow.name === "template" || attrRow.name === "inherit")) { // missing handling of things inherited from template refreshCtx.noteIdsToReload.add(attrRow.noteId); - } else if (attrRow.type === "relation" && attrRow.name === "imageLink") { + } else if (attrRow.type === "relation" && attrRow.name === "imageLink" && attrRow.noteId) { const note = froca.getNoteFromCache(attrRow.noteId); - if (note && note.getChildNoteIds().includes(attrRow.value)) { + if (note && note.getChildNoteIds().includes(attrRow.value ?? "")) { // there's a new /deleted imageLink between note and its image child - which can show/hide // the image (if there is an imageLink relation between parent and child, // then it is assumed to be "contained" in the note and thus does not have to be displayed in the tree) @@ -1178,7 +1226,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - async #processBranchRows(branchRows, refreshCtx) { + async #processBranchRows(branchRows: BranchRow[], refreshCtx) { const allBranchesDeleted = branchRows.every((branchRow) => !!branchRow.isDeleted); // activeNode is supposed to be moved when we find out activeNode is deleted but not all branches are deleted. save it for fixing activeNodePath after all nodes loaded. @@ -1223,19 +1271,19 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } const note = await froca.getNote(branchRow.noteId); - const frocaBranch = froca.getBranch(branchRow.branchId); + const frocaBranch = branchRow.branchId ? froca.getBranch(branchRow.branchId) : null; const foundNode = (parentNode.getChildren() || []).find((child) => child.data.noteId === branchRow.noteId); if (foundNode) { // the branch already exists in the tree - if (branchRow.isExpanded !== foundNode.isExpanded()) { + if (branchRow.isExpanded !== foundNode.isExpanded() && frocaBranch) { refreshCtx.noteIdsToReload.add(frocaBranch.noteId); } - } else { + } else if (frocaBranch) { // make sure it's loaded // we're forcing lazy since it's not clear if the whole required subtree is in froca parentNode.addChildren([this.prepareNode(frocaBranch, true)]); - if (frocaBranch.isExpanded && note.hasChildren()) { + if (frocaBranch?.isExpanded && note && note.hasChildren()) { refreshCtx.noteIdsToReload.add(frocaBranch.noteId); } @@ -1254,7 +1302,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { }; } - async #executeTreeUpdates(refreshCtx, loadResults) { + async #executeTreeUpdates(refreshCtx, loadResults: LoadResults) { await this.batchUpdate(async () => { for (const noteId of refreshCtx.noteIdsToReload) { for (const node of this.getNodesByNoteId(noteId)) { @@ -1281,7 +1329,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - async #setActiveNode(activeNotePath, activeNodeFocused, movedActiveNode, parentsOfAddedNodes) { + async #setActiveNode(activeNotePath: string | null, activeNodeFocused: boolean, movedActiveNode: Fancytree.FancytreeNode, parentsOfAddedNodes: Fancytree.FancytreeNode[]) { if (movedActiveNode) { for (const parentNode of parentsOfAddedNodes) { const foundNode = (parentNode.getChildren() || []).find((child) => child.data.noteId === movedActiveNode.data.noteId); @@ -1319,7 +1367,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { await node.setActive(true, { noEvents: true, noFocus: !activeNodeFocused }); } - sortChildren(node) { + sortChildren(node: Fancytree.FancytreeNode) { node.sortChildren((nodeA, nodeB) => { const branchA = froca.branches[nodeA.data.branchId]; const branchB = froca.branches[nodeB.data.branchId]; @@ -1332,7 +1380,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { }); } - setExpanded(branchId, isExpanded) { + setExpanded(branchId: string, isExpanded: boolean) { utils.assertArguments(branchId); const branch = froca.getBranch(branchId, true); @@ -1374,7 +1422,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - async hoistedNoteChangedEvent({ ntxId }) { + async hoistedNoteChangedEvent({ ntxId }: EventData<"hoistedNoteChanged">) { if (this.isNoteContext(ntxId)) { await this.filterHoistedBranch(true); } @@ -1404,7 +1452,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { // hack when hoisted note is cloned then it could be filtered multiple times while we want only 1 this.tree.filterBranches( (node) => - node.data.noteId === this.noteContext.hoistedNoteId && // optimization to not having always resolve the node path + node.data.noteId === this.noteContext?.hoistedNoteId && // optimization to not having always resolve the node path treeService.getNotePath(node) === hoistedNotePath ); @@ -1412,18 +1460,18 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - toggleHiddenNode(show) { + toggleHiddenNode(show: boolean) { const hiddenNode = this.getNodesByNoteId("_hidden")[0]; $(hiddenNode.li).toggleClass("hidden-node-is-hidden", !show); } - frocaReloadedEvent() { + async frocaReloadedEvent() { this.reloadTreeFromCache(); } async getHotKeys() { const actions = await keyboardActionsService.getActionsForScope("note-tree"); - const hotKeyMap = {}; + const hotKeyMap: Record boolean> = {}; for (const action of actions) { for (const shortcut of action.effectiveShortcuts) { @@ -1440,25 +1488,19 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return hotKeyMap; } - /** - * @param {FancytreeNode} node - */ - getSelectedOrActiveBranchIds(node) { + getSelectedOrActiveBranchIds(node: Fancytree.FancytreeNode) { const nodes = this.getSelectedOrActiveNodes(node); return nodes.map((node) => node.data.branchId); } - /** - * @param {FancytreeNode} node - */ - getSelectedOrActiveNoteIds(node) { + getSelectedOrActiveNoteIds(node: Fancytree.FancytreeNode): string[] { const nodes = this.getSelectedOrActiveNodes(node); return nodes.map((node) => node.data.noteId); } - async deleteNotesCommand({ node }) { + async deleteNotesCommand({ node }: CommandListenerData<"deleteNotes">) { const branchIds = this.getSelectedOrActiveBranchIds(node).filter((branchId) => !branchId.startsWith("virt-")); // search results can't be deleted if (!branchIds.length) { @@ -1470,7 +1512,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { this.clearSelectedNodes(); } - canBeMovedUpOrDown(node) { + canBeMovedUpOrDown(node: Fancytree.FancytreeNode) { if (node.data.noteId === "root") { return false; } @@ -1480,8 +1522,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { return !parentNote?.hasLabel("sorted"); } - moveNoteUpCommand({ node }) { - if (!this.canBeMovedUpOrDown(node)) { + moveNoteUpCommand({ node }: CommandListenerData<"moveNoteUp">) { + if (!node || !this.canBeMovedUpOrDown(node)) { return; } @@ -1492,7 +1534,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - moveNoteDownCommand({ node }) { + moveNoteDownCommand({ node }: CommandListenerData<"moveNoteDown">) { if (!this.canBeMovedUpOrDown(node)) { return; } @@ -1504,11 +1546,11 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - moveNoteUpInHierarchyCommand({ node }) { + moveNoteUpInHierarchyCommand({ node }: CommandListenerData<"moveNoteUpInHierarchy">) { branchService.moveNodeUpInHierarchy(node); } - moveNoteDownInHierarchyCommand({ node }) { + moveNoteDownInHierarchyCommand({ node }: CommandListenerData<"moveNoteDownInHierarchy">) { const toNode = node.getPrevSibling(); if (toNode !== null) { @@ -1564,63 +1606,63 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - expandSubtreeCommand({ node }) { + expandSubtreeCommand({ node }: CommandListenerData<"expandSubtree">) { this.expandTree(node); } - collapseSubtreeCommand({ node }) { + collapseSubtreeCommand({ node }: CommandListenerData<"collapseSubtree">) { this.collapseTree(node); } - async recentChangesInSubtreeCommand({ node }) { + async recentChangesInSubtreeCommand({ node }: CommandListenerData<"recentChangesInSubtree">) { this.triggerCommand("showRecentChanges", { ancestorNoteId: node.data.noteId }); } - selectAllNotesInParentCommand({ node }) { + selectAllNotesInParentCommand({ node }: CommandListenerData<"selectAllNotesInParent">) { for (const child of node.getParent().getChildren()) { child.setSelected(true); } } - copyNotesToClipboardCommand({ node }) { + copyNotesToClipboardCommand({ node }: CommandListenerData<"copyNotesToClipboard">) { clipboard.copy(this.getSelectedOrActiveBranchIds(node)); } - cutNotesToClipboardCommand({ node }) { + cutNotesToClipboardCommand({ node }: CommandListenerData<"cutNotesToClipboard">) { clipboard.cut(this.getSelectedOrActiveBranchIds(node)); } - pasteNotesFromClipboardCommand({ node }) { + pasteNotesFromClipboardCommand({ node }: CommandListenerData<"pasteNotesFromClipboard">) { clipboard.pasteInto(node.data.branchId); } - pasteNotesAfterFromClipboardCommand({ node }) { + pasteNotesAfterFromClipboardCommand({ node }: CommandListenerData<"pasteNotesAfterFromClipboard">) { clipboard.pasteAfter(node.data.branchId); } - async exportNoteCommand({ node }) { + async exportNoteCommand({ node }: CommandListenerData<"exportNote">) { const notePath = treeService.getNotePath(node); this.triggerCommand("showExportDialog", { notePath, defaultType: "subtree" }); } - async importIntoNoteCommand({ node }) { + async importIntoNoteCommand({ node }: CommandListenerData<"importIntoNote">) { this.triggerCommand("showImportDialog", { noteId: node.data.noteId }); } - editNoteTitleCommand({ node }) { + editNoteTitleCommand({ node }: CommandListenerData<"editNoteTitle">) { appContext.triggerCommand("focusOnTitle"); } - protectSubtreeCommand({ node }) { + protectSubtreeCommand({ node }: CommandListenerData<"protectSubtree">) { protectedSessionService.protectNote(node.data.noteId, true, true); } - unprotectSubtreeCommand({ node }) { + unprotectSubtreeCommand({ node }: CommandListenerData<"unprotectSubtree">) { protectedSessionService.protectNote(node.data.noteId, false, true); } - duplicateSubtreeCommand({ node }) { + duplicateSubtreeCommand({ node }: CommandListenerData<"duplicateSubtree">) { const nodesToDuplicate = this.getSelectedOrActiveNodes(node); for (const nodeToDuplicate of nodesToDuplicate) { @@ -1632,19 +1674,21 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { const branch = froca.getBranch(nodeToDuplicate.data.branchId); - noteCreateService.duplicateSubtree(nodeToDuplicate.data.noteId, branch.parentNoteId); + if (branch?.parentNoteId) { + noteCreateService.duplicateSubtree(nodeToDuplicate.data.noteId, branch.parentNoteId); + } } } - moveLauncherToVisibleCommand({ selectedOrActiveBranchIds }) { + moveLauncherToVisibleCommand({ selectedOrActiveBranchIds }: CommandListenerData<"moveLauncherToVisible">) { this.#moveLaunchers(selectedOrActiveBranchIds, "_lbVisibleLaunchers", "_lbMobileVisibleLaunchers"); } - moveLauncherToAvailableCommand({ selectedOrActiveBranchIds }) { + moveLauncherToAvailableCommand({ selectedOrActiveBranchIds }: CommandListenerData<"moveLauncherToAvailable">) { this.#moveLaunchers(selectedOrActiveBranchIds, "_lbAvailableLaunchers", "_lbMobileAvailableLaunchers"); } - #moveLaunchers(selectedOrActiveBranchIds, desktopParent, mobileParent) { + #moveLaunchers(selectedOrActiveBranchIds: string[], desktopParent: string, mobileParent: string) { const desktopLaunchersToMove = selectedOrActiveBranchIds.filter((branchId) => !branchId.startsWith("_lbMobile")); if (desktopLaunchersToMove) { branchService.moveToParentNote(desktopLaunchersToMove, "_lbRoot_" + desktopParent); @@ -1656,24 +1700,24 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { } } - addNoteLauncherCommand({ node }) { + addNoteLauncherCommand({ node }: CommandListenerData<"addNoteLauncher">) { this.createLauncherNote(node, "note"); } - addScriptLauncherCommand({ node }) { + addScriptLauncherCommand({ node }: CommandListenerData<"addScriptLauncher">) { this.createLauncherNote(node, "script"); } - addWidgetLauncherCommand({ node }) { + addWidgetLauncherCommand({ node }: CommandListenerData<"addWidgetLauncher">) { this.createLauncherNote(node, "customWidget"); } - addSpacerLauncherCommand({ node }) { + addSpacerLauncherCommand({ node }: CommandListenerData<"addSpacerLauncher">) { this.createLauncherNote(node, "spacer"); } - async createLauncherNote(node, launcherType) { - const resp = await server.post(`special-notes/launchers/${node.data.noteId}/${launcherType}`); + async createLauncherNote(node: Fancytree.FancytreeNode, launcherType: LauncherType) { + const resp = await server.post(`special-notes/launchers/${node.data.noteId}/${launcherType}`); if (!resp.success) { toastService.showError(resp.message); diff --git a/src/services/special_notes.ts b/src/services/special_notes.ts index 2c5b2cf4f..c8dded954 100644 --- a/src/services/special_notes.ts +++ b/src/services/special_notes.ts @@ -158,7 +158,7 @@ function createScriptLauncher(parentNoteId: string, forceNoteId?: string) { interface LauncherConfig { parentNoteId: string; - launcherType: string; + launcherType: "launcher" | "note" | "script" | "customWidget" | "spacer"; noteId?: string; } From 2ab22e7b0ed5e1318560844f606f446d5789cb51 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 24 Feb 2025 12:39:40 +0200 Subject: [PATCH 2/5] fix(client): type errors due to command change --- src/public/app/components/app_context.ts | 21 +++++++++++++------ src/public/app/components/component.ts | 3 +-- src/public/app/menus/launcher_context_menu.ts | 4 ++-- src/public/app/menus/tree_context_menu.ts | 4 ++-- src/public/app/services/hoisted_note.ts | 6 +++--- src/routes/api/special_notes.ts | 5 +++-- src/services/special_notes.ts | 4 +++- 7 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index 029182a86..408abd62d 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -56,7 +56,7 @@ export interface ContextMenuCommandData extends CommandData { } export interface NoteCommandData extends CommandData { - notePath: string; + notePath?: string; hoistedNoteId?: string; viewScope?: ViewScope; } @@ -79,6 +79,7 @@ export type CommandMappings = { ancestorNoteId?: string | null; }; closeTocCommand: CommandData; + closeHlt: CommandData; showLaunchBarSubtree: CommandData; showRevisions: CommandData; showOptions: CommandData & { @@ -113,6 +114,8 @@ export type CommandMappings = { openNoteInNewTab: CommandData; openNoteInNewSplit: CommandData; openNoteInNewWindow: CommandData; + openAboutDialog: CommandData; + hideFloatingButtons: {}; hideLeftPane: CommandData; showLeftPane: CommandData; hoistNote: CommandData & { noteId: string }; @@ -129,7 +132,7 @@ export type CommandMappings = { protectSubtree: ContextMenuCommandData; unprotectSubtree: ContextMenuCommandData; openBulkActionsDialog: ContextMenuCommandData | { - selectedOrActiveNoteIds: string[] + selectedOrActiveNoteIds?: string[] }; editBranchPrefix: ContextMenuCommandData; convertNoteToAttachment: ContextMenuCommandData; @@ -186,6 +189,7 @@ export type CommandMappings = { importMarkdownInline: CommandData; showPasswordNotSet: CommandData; showProtectedSessionPasswordDialog: CommandData; + showUploadAttachmentsDialog: CommandData & { noteId: string }; closeProtectedSessionPasswordDialog: CommandData; copyImageReferenceToClipboard: CommandData; copyImageToClipboard: CommandData; @@ -209,6 +213,7 @@ export type CommandMappings = { screen: Screen; }; closeTab: CommandData; + closeToc: CommandData; closeOtherTabs: CommandData; closeRightTabs: CommandData; closeAllTabs: CommandData; @@ -227,15 +232,20 @@ export type CommandMappings = { scrollContainerToCommand: CommandData & { position: number; }; - moveThisNoteSplit: CommandData & { - isMovingLeft: boolean; - }; + scrollToEnd: CommandData; + closeThisNoteSplit: CommandData; + moveThisNoteSplit: CommandData & { isMovingLeft: boolean; }; // Geomap deleteFromMap: { noteId: string }, openGeoLocation: { noteId: string, event: JQuery.MouseDownEvent } toggleZenMode: CommandData; + + updateAttributeList: CommandData & { attributes: Attribute[] }; + saveAttributes: CommandData; + reloadAttributes: CommandData; + refreshNoteList: CommandData & { noteId: string; }; }; type EventMappings = { @@ -336,7 +346,6 @@ type EventMappings = { showToc: { noteId: string; }; - scrollToEnd: { ntxId: string }; noteTypeMimeChanged: { noteId: string }; zenModeChanged: { isEnabled: boolean }; }; diff --git a/src/public/app/components/component.ts b/src/public/app/components/component.ts index ad35e911d..416449fc7 100644 --- a/src/public/app/components/component.ts +++ b/src/public/app/components/component.ts @@ -80,8 +80,7 @@ export class TypedComponent> { return promises.length > 0 ? Promise.all(promises) : null; } - triggerCommand(name: K, _data?: CommandMappings[K]): Promise | undefined | null { - const data = _data || {}; + triggerCommand(name: K, data?: CommandMappings[K]): Promise | undefined | null { const fun = (this as any)[`${name}Command`]; if (fun) { diff --git a/src/public/app/menus/launcher_context_menu.ts b/src/public/app/menus/launcher_context_menu.ts index bc219e591..3aa436632 100644 --- a/src/public/app/menus/launcher_context_menu.ts +++ b/src/public/app/menus/launcher_context_menu.ts @@ -21,8 +21,8 @@ export default class LauncherContextMenu implements SelectMenuItemEventListener< async show(e: PointerEvent | JQuery.TouchStartEvent | JQuery.ContextMenuEvent) { contextMenu.show({ - x: e.pageX, - y: e.pageY, + x: e.pageX ?? 0, + y: e.pageY ?? 0, items: await this.getMenuItems(), selectMenuItemHandler: (item, e) => this.selectMenuItemHandler(item) }); diff --git a/src/public/app/menus/tree_context_menu.ts b/src/public/app/menus/tree_context_menu.ts index c1bf3b07b..96872b484 100644 --- a/src/public/app/menus/tree_context_menu.ts +++ b/src/public/app/menus/tree_context_menu.ts @@ -31,8 +31,8 @@ export default class TreeContextMenu implements SelectMenuItemEventListener this.selectMenuItemHandler(item) }); diff --git a/src/public/app/services/hoisted_note.ts b/src/public/app/services/hoisted_note.ts index 597de9467..f41f08e06 100644 --- a/src/public/app/services/hoisted_note.ts +++ b/src/public/app/services/hoisted_note.ts @@ -1,5 +1,5 @@ import appContext from "../components/app_context.js"; -import treeService, { type Node } from "./tree.js"; +import treeService from "./tree.js"; import dialogService from "./dialog.js"; import froca from "./froca.js"; import type NoteContext from "../components/note_context.js"; @@ -19,11 +19,11 @@ async function unhoist() { } } -function isTopLevelNode(node: Node) { +function isTopLevelNode(node: Fancytree.FancytreeNode) { return isHoistedNode(node.getParent()); } -function isHoistedNode(node: Node) { +function isHoistedNode(node: Fancytree.FancytreeNode) { // even though check for 'root' should not be necessary, we keep it just in case return node.data.noteId === "root" || node.data.noteId === getHoistedNoteId(); } diff --git a/src/routes/api/special_notes.ts b/src/routes/api/special_notes.ts index cf339794b..b443f9ec3 100644 --- a/src/routes/api/special_notes.ts +++ b/src/routes/api/special_notes.ts @@ -3,7 +3,7 @@ import dateNoteService from "../../services/date_notes.js"; import sql from "../../services/sql.js"; import cls from "../../services/cls.js"; -import specialNotesService from "../../services/special_notes.js"; +import specialNotesService, { type LauncherType } from "../../services/special_notes.js"; import becca from "../../becca/becca.js"; import type { Request } from "express"; @@ -85,7 +85,8 @@ function getHoistedNote() { function createLauncher(req: Request) { return specialNotesService.createLauncher({ parentNoteId: req.params.parentNoteId, - launcherType: req.params.launcherType + // TODO: Validate the parameter + launcherType: req.params.launcherType as LauncherType }); } diff --git a/src/services/special_notes.ts b/src/services/special_notes.ts index c8dded954..11c0fd2bc 100644 --- a/src/services/special_notes.ts +++ b/src/services/special_notes.ts @@ -156,9 +156,11 @@ function createScriptLauncher(parentNoteId: string, forceNoteId?: string) { return note; } +export type LauncherType = "launcher" | "note" | "script" | "customWidget" | "spacer"; + interface LauncherConfig { parentNoteId: string; - launcherType: "launcher" | "note" | "script" | "customWidget" | "spacer"; + launcherType: LauncherType; noteId?: string; } From 65804f9c2aa72c89edf6c55f3569d2b2807d4d4a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 24 Feb 2025 17:46:44 +0200 Subject: [PATCH 3/5] chore(deps): revert changges to package-lock --- package-lock.json | 1438 +++++++++++++++++++++++++++------------------ 1 file changed, 881 insertions(+), 557 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccd1a724b..569991c4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1718,9 +1718,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", "cpu": [ "ppc64" ], @@ -1735,9 +1735,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], @@ -1752,9 +1752,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], @@ -1769,9 +1769,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], @@ -1786,9 +1786,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], @@ -1803,9 +1803,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], @@ -1820,9 +1820,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], @@ -1837,9 +1837,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], @@ -1854,9 +1854,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], @@ -1871,9 +1871,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], @@ -1888,9 +1888,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], @@ -1905,9 +1905,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], @@ -1922,9 +1922,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], @@ -1939,9 +1939,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], @@ -1956,9 +1956,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], @@ -1973,9 +1973,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], @@ -2024,9 +2024,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], @@ -2041,9 +2041,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", "cpu": [ "arm64" ], @@ -2058,9 +2058,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], @@ -2075,9 +2075,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], @@ -2092,9 +2092,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], @@ -2109,9 +2109,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], @@ -2126,9 +2126,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], @@ -3620,9 +3620,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz", - "integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz", + "integrity": "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==", "cpu": [ "arm" ], @@ -3634,9 +3634,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz", - "integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.1.tgz", + "integrity": "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==", "cpu": [ "arm64" ], @@ -3648,9 +3648,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz", - "integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz", + "integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==", "cpu": [ "arm64" ], @@ -3662,9 +3662,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz", - "integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.1.tgz", + "integrity": "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==", "cpu": [ "x64" ], @@ -3676,9 +3676,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz", - "integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.1.tgz", + "integrity": "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==", "cpu": [ "arm64" ], @@ -3690,9 +3690,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz", - "integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz", + "integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==", "cpu": [ "x64" ], @@ -3704,9 +3704,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz", - "integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.1.tgz", + "integrity": "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==", "cpu": [ "arm" ], @@ -3718,9 +3718,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz", - "integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.1.tgz", + "integrity": "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==", "cpu": [ "arm" ], @@ -3732,9 +3732,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz", - "integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.1.tgz", + "integrity": "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==", "cpu": [ "arm64" ], @@ -3746,9 +3746,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz", - "integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.1.tgz", + "integrity": "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==", "cpu": [ "arm64" ], @@ -3760,9 +3760,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz", - "integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.1.tgz", + "integrity": "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==", "cpu": [ "loong64" ], @@ -3774,9 +3774,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz", - "integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.1.tgz", + "integrity": "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==", "cpu": [ "ppc64" ], @@ -3788,9 +3788,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz", - "integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.1.tgz", + "integrity": "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==", "cpu": [ "riscv64" ], @@ -3802,9 +3802,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz", - "integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.1.tgz", + "integrity": "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==", "cpu": [ "s390x" ], @@ -3816,9 +3816,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz", - "integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.1.tgz", + "integrity": "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==", "cpu": [ "x64" ], @@ -3830,9 +3830,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz", - "integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.1.tgz", + "integrity": "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==", "cpu": [ "x64" ], @@ -3844,9 +3844,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz", - "integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.1.tgz", + "integrity": "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==", "cpu": [ "arm64" ], @@ -3858,9 +3858,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz", - "integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.1.tgz", + "integrity": "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==", "cpu": [ "ia32" ], @@ -3872,9 +3872,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz", - "integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.1.tgz", + "integrity": "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==", "cpu": [ "x64" ], @@ -3889,8 +3889,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", - "hasInstallScript": true, - "license": "Apache-2.0" + "hasInstallScript": true }, "node_modules/@shikijs/engine-oniguruma": { "version": "1.24.2", @@ -5508,6 +5507,44 @@ "node": ">= 8" } }, + "node_modules/appdmg": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/appdmg/-/appdmg-0.6.6.tgz", + "integrity": "sha512-GRmFKlCG+PWbcYF4LUNonTYmy0GjguDy6Jh9WP8mpd0T6j80XIJyXBiWlD0U+MLNhqV9Nhx49Gl9GpVToulpLg==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "async": "^1.4.2", + "ds-store": "^0.1.5", + "execa": "^1.0.0", + "fs-temp": "^1.0.0", + "fs-xattr": "^0.3.0", + "image-size": "^0.7.4", + "is-my-json-valid": "^2.20.0", + "minimist": "^1.1.3", + "parse-color": "^1.0.0", + "path-exists": "^4.0.0", + "repeat-string": "^1.5.4" + }, + "bin": { + "appdmg": "bin/appdmg.js" + }, + "engines": { + "node": ">=8.5" + } + }, + "node_modules/appdmg/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", @@ -5817,6 +5854,17 @@ "license": "Apache-2.0", "optional": true }, + "node_modules/base32-encode": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/base32-encode/-/base32-encode-1.2.0.tgz", + "integrity": "sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "to-data-view": "^1.1.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -6093,6 +6141,17 @@ "object-assign": "^4.1.1" } }, + "node_modules/bplist-creator": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", + "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "stream-buffers": "~2.2.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -8380,6 +8439,19 @@ "unidragger": "^3.0.0" } }, + "node_modules/ds-store": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ds-store/-/ds-store-0.1.6.tgz", + "integrity": "sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bplist-creator": "~0.0.3", + "macos-alias": "~0.2.5", + "tn1150": "^0.1.0" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -9143,9 +9215,9 @@ } }, "node_modules/electron/node_modules/@types/node": { - "version": "20.17.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.16.tgz", - "integrity": "sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw==", + "version": "20.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.19.tgz", + "integrity": "sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -9210,6 +9282,14 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -9399,278 +9479,6 @@ "@esbuild/win32-x64": "0.25.0" } }, - "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/esbuild/node_modules/@esbuild/netbsd-arm64": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", @@ -9688,125 +9496,6 @@ "node": ">=18" } }, - "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/win32-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", - "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -10641,6 +10330,17 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/fmix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fmix/-/fmix-0.1.0.tgz", + "integrity": "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "imul": "^1.0.0" + } + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -10806,6 +10506,32 @@ "node": ">= 8" } }, + "node_modules/fs-temp": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/fs-temp/-/fs-temp-1.2.1.tgz", + "integrity": "sha512-okTwLB7/Qsq82G6iN5zZJFsOfZtx2/pqrA7Hk/9fvy+c+eJS9CvgGXT2uNxwnI14BDY9L/jQPkaBgSvlKfSW9w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "random-path": "^0.1.0" + } + }, + "node_modules/fs-xattr": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/fs-xattr/-/fs-xattr-0.3.1.tgz", + "integrity": "sha512-UVqkrEW0GfDabw4C3HOrFlxKfx0eeigfRne69FxSBdHIP8Qt5Sq6Pu3RM9KmMlkygtC4pPKkj5CiPO5USnj2GA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "!win32" + ], + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -10889,6 +10615,28 @@ "license": "MIT", "optional": true }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-property": "^1.0.0" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -11626,6 +11374,20 @@ "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", "license": "MIT" }, + "node_modules/image-size": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz", + "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/image-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/image-type/-/image-type-5.2.0.tgz", @@ -11691,6 +11453,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imul": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz", + "integrity": "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -11924,6 +11697,29 @@ "dev": true, "license": "MIT" }, + "node_modules/is-my-ip-valid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", + "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/is-my-json-valid": { + "version": "2.20.6", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", + "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -11957,6 +11753,14 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "license": "MIT" }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -12263,7 +12067,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -12428,6 +12231,17 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/jsplumb": { "version": "2.15.6", "resolved": "https://registry.npmjs.org/jsplumb/-/jsplumb-2.15.6.tgz", @@ -12878,6 +12692,21 @@ "dev": true, "license": "MIT" }, + "node_modules/macos-alias": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/macos-alias/-/macos-alias-0.2.12.tgz", + "integrity": "sha512-yiLHa7cfJcGRFq4FrR4tMlpNHb4Vy4mWnpajlSSIFM5k4Lv8/7BbbDLzCAVogWNl0LlLhizRp1drXv0hK9h0Yw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "nan": "^2.4.0" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -13472,6 +13301,27 @@ "node": ">= 6.0.0" } }, + "node_modules/murmur-32": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/murmur-32/-/murmur-32-0.2.0.tgz", + "integrity": "sha512-ZkcWZudylwF+ir3Ld1n7gL6bI2mQAzXvSobPwVtu8aYi2sbXeipeSkdcanRLzIofLcM5F53lGaKm2dk7orBi7Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "encode-utf8": "^1.0.3", + "fmix": "^0.1.0", + "imul": "^1.0.0" + } + }, + "node_modules/nan": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/nanoid": { "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", @@ -14189,6 +14039,24 @@ "node": ">=4.0" } }, + "node_modules/parse-color": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", + "integrity": "sha512-fuDHYgFHJGbpGMgw9skY/bj3HL/Jrn4l/5rSspy00DoT4RyLnDcRvPxdZ+r6OFwIsgAuhDh4I09tAId4mI12bw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "~0.5.0" + } + }, + "node_modules/parse-color/node_modules/color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==", + "dev": true, + "optional": true + }, "node_modules/parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -14604,9 +14472,9 @@ } }, "node_modules/postcss": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -15033,6 +14901,18 @@ "node": ">= 0.8" } }, + "node_modules/random-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/random-path/-/random-path-0.1.2.tgz", + "integrity": "sha512-4jY0yoEaQ5v9StCl5kZbNIQlg1QheIDBrdkDn53EynpPb9FgO6//p3X/tgMnrC45XN6QZCzU1Xz/+pSSsJBpRw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "base32-encode": "^0.1.0 || ^1.0.0", + "murmur-32": "^0.1.0 || ^0.2.0" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -15488,6 +15368,17 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "license": "MIT" }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -15812,9 +15703,9 @@ "license": "Unlicense" }, "node_modules/rollup": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz", - "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz", + "integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==", "dev": true, "license": "MIT", "dependencies": { @@ -15828,25 +15719,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.6", - "@rollup/rollup-android-arm64": "4.34.6", - "@rollup/rollup-darwin-arm64": "4.34.6", - "@rollup/rollup-darwin-x64": "4.34.6", - "@rollup/rollup-freebsd-arm64": "4.34.6", - "@rollup/rollup-freebsd-x64": "4.34.6", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", - "@rollup/rollup-linux-arm-musleabihf": "4.34.6", - "@rollup/rollup-linux-arm64-gnu": "4.34.6", - "@rollup/rollup-linux-arm64-musl": "4.34.6", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", - "@rollup/rollup-linux-riscv64-gnu": "4.34.6", - "@rollup/rollup-linux-s390x-gnu": "4.34.6", - "@rollup/rollup-linux-x64-gnu": "4.34.6", - "@rollup/rollup-linux-x64-musl": "4.34.6", - "@rollup/rollup-win32-arm64-msvc": "4.34.6", - "@rollup/rollup-win32-ia32-msvc": "4.34.6", - "@rollup/rollup-win32-x64-msvc": "4.34.6", + "@rollup/rollup-android-arm-eabi": "4.30.1", + "@rollup/rollup-android-arm64": "4.30.1", + "@rollup/rollup-darwin-arm64": "4.30.1", + "@rollup/rollup-darwin-x64": "4.30.1", + "@rollup/rollup-freebsd-arm64": "4.30.1", + "@rollup/rollup-freebsd-x64": "4.30.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.30.1", + "@rollup/rollup-linux-arm-musleabihf": "4.30.1", + "@rollup/rollup-linux-arm64-gnu": "4.30.1", + "@rollup/rollup-linux-arm64-musl": "4.30.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.30.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.30.1", + "@rollup/rollup-linux-riscv64-gnu": "4.30.1", + "@rollup/rollup-linux-s390x-gnu": "4.30.1", + "@rollup/rollup-linux-x64-gnu": "4.30.1", + "@rollup/rollup-linux-x64-musl": "4.30.1", + "@rollup/rollup-win32-arm64-msvc": "4.30.1", + "@rollup/rollup-win32-ia32-msvc": "4.30.1", + "@rollup/rollup-win32-x64-msvc": "4.30.1", "fsevents": "~2.3.2" } }, @@ -16065,9 +15956,9 @@ } }, "node_modules/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -16714,6 +16605,17 @@ "dev": true, "license": "MIT" }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "dev": true, + "license": "Unlicense", + "optional": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/stream-throttle": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", @@ -17090,7 +16992,6 @@ "version": "5.18.3", "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.18.3.tgz", "integrity": "sha512-G33HFW0iFNStfY2x6QXO2JYVMrFruc8AZRX0U/L71aA7WeWfX2E5Nm8E/tsipSZJeIZZbSjUDeynLK/wcuNWIw==", - "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" } @@ -17099,7 +17000,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", - "license": "MIT", "dependencies": { "swagger-ui-dist": ">=5.0.0" }, @@ -17524,6 +17424,28 @@ "tmp": "^0.2.0" } }, + "node_modules/tn1150": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tn1150/-/tn1150-0.1.0.tgz", + "integrity": "sha512-DbplOfQFkqG5IHcDyyrs/lkvSr3mPUVsFf/RbDppOshs22yTPnSJWEe6FkYd1txAwU/zcnR905ar2fi4kwF29w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "unorm": "^1.4.1" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/to-data-view": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/to-data-view/-/to-data-view-1.1.0.tgz", + "integrity": "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -17948,6 +17870,17 @@ "node": ">= 10.0.0" } }, + "node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "dev": true, + "license": "MIT or GPL-2.0", + "optional": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -18124,14 +18057,14 @@ } }, "node_modules/vite": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", - "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz", + "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.5.1", + "postcss": "^8.5.2", "rollup": "^4.30.1" }, "bin": { @@ -18225,6 +18158,278 @@ "dev": true, "license": "MIT" }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/vite/node_modules/@esbuild/linux-x64": { "version": "0.24.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", @@ -18242,6 +18447,125 @@ "node": ">=18" } }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/vite/node_modules/esbuild": { "version": "0.24.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", From 7874e88b4ac54759d4f44b761911c3933aa45fe2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 24 Feb 2025 21:30:57 +0200 Subject: [PATCH 4/5] fix(build): fancytree's JQuery UI interfering with bootstrap --- package-lock.json | 22 - package.json | 1 - src/public/app/types-fancytree.d.ts | 1165 +++++++++++++++++++++++++++ 3 files changed, 1165 insertions(+), 23 deletions(-) create mode 100644 src/public/app/types-fancytree.d.ts diff --git a/package-lock.json b/package-lock.json index 569991c4d..ea3fa65ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -137,7 +137,6 @@ "@types/html": "1.0.4", "@types/ini": "4.1.1", "@types/jquery": "3.5.32", - "@types/jquery.fancytree": "0.0.11", "@types/js-yaml": "4.0.9", "@types/jsdom": "21.1.7", "@types/leaflet": "1.9.16", @@ -4508,27 +4507,6 @@ "@types/sizzle": "*" } }, - "node_modules/@types/jquery.fancytree": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@types/jquery.fancytree/-/jquery.fancytree-0.0.11.tgz", - "integrity": "sha512-ga0wwAa8SLSAxdg+kU6wH8PMY/XxWx+rOzzQz4z1t1GSj/9suYakgQhcAT2gVk6yBdzYHT8ltpkhfCxhEtk0Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jquery": "*", - "@types/jqueryui": "*" - } - }, - "node_modules/@types/jqueryui": { - "version": "1.12.23", - "resolved": "https://registry.npmjs.org/@types/jqueryui/-/jqueryui-1.12.23.tgz", - "integrity": "sha512-pm1yVNVI29B9IGw41anCEzA5eR2r1pYc7flqD471ZT7B0yUXIY7YNe/zq7LGpihIGXNzWyG+Q4YQSzv2AF3fNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jquery": "*" - } - }, "node_modules/@types/js-yaml": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", diff --git a/package.json b/package.json index d016991a1..cf4adaf71 100644 --- a/package.json +++ b/package.json @@ -184,7 +184,6 @@ "@types/html": "1.0.4", "@types/ini": "4.1.1", "@types/jquery": "3.5.32", - "@types/jquery.fancytree": "0.0.11", "@types/js-yaml": "4.0.9", "@types/jsdom": "21.1.7", "@types/leaflet": "1.9.16", diff --git a/src/public/app/types-fancytree.d.ts b/src/public/app/types-fancytree.d.ts new file mode 100644 index 000000000..c016dad8a --- /dev/null +++ b/src/public/app/types-fancytree.d.ts @@ -0,0 +1,1165 @@ +/* + ! This is an altered copy of the @types/jquery.fancytree definition as of version 0.0.11. + + The reason for this is that upstream also brings the whole type definitions of JQuery UI + which conflicts with bootstrap's globals such as .tooltip. Due to this, we are removing the + reference to jquery UI and inject the globals ourselves. + */ + +//#region Changes +/// + +interface JQueryStatic { + ui: JQueryUI.UI; +}; + +declare namespace JQueryUI { + interface UI { + fancytree: Fancytree.FancytreeStatic; + } +} + +//#endregion + +//#region Same as upstream (0.0.11) +interface JQuery { + fancytree(options?: Fancytree.FancytreeOptions): Fancytree.Fancytree; + fancytree(option?: string, ...rest: any[]): any; +} + +declare namespace Fancytree { + interface Fancytree { + $div: JQuery; + widget: any; // JQueryUI.Widget; + rootNode: FancytreeNode; + $container: JQuery; + focusNode: FancytreeNode; + options: FancytreeOptions; + + /** Activate node with a given key and fire focus and + * activate events. A previously activated node will be + * deactivated. If activeVisible option is set, all parents + * will be expanded as necessary. Pass key = false, to deactivate + * the current node only. + * + * @returns {FancytreeNode} activate node (null, if not found) + */ + activateKey(key: string | boolean): FancytreeNode; + + /** (experimental) + * + * @returns resolved, when all patches have been applied + */ + applyPatch(patchList: NodePatch[]): JQueryPromise; + + /** [ext-clones] Replace a refKey with a new one. */ + changeRefKey(oldRefKey: string, newRefKey: string): void; + + /** [ext-persist] Remove persistence cookies of the given type(s). + * Called like $("#tree").fancytree("getTree").clearCookies("active expanded focus selected"); */ + clearCookies(): void; + + /** [ext-filter] Reset the filter. */ + clearFilter(): void; + + /** Return the number of nodes. */ + count(): number; + + /** Write to browser console if debugLevel >= 2 (prepending tree name) */ + debug(msg: any): void; + + /** Expand (or collapse) all parent nodes. */ + expandAll(flag?: boolean, options?: Object): void; + + /** [ext-filter] Dimm or hide whole branches. + * @returns {integer} count + */ + filterBranches(filter: string): number; + + /** [ext-filter] Dimm or hide whole branches. + * @returns {integer} count + */ + filterBranches(filter: (node: FancytreeNode) => boolean): number; + + /** [ext-filter] Dimm or hide nodes. + * @returns {integer} count + */ + filterNodes(filter: string, leavesOnly?: boolean): number; + + /** [ext-filter] Dimm or hide nodes. + * @returns {integer} count + */ + filterNodes(filter: (node: FancytreeNode) => boolean, leavesOnly?: boolean): number; + + /** Find the next visible node that starts with `match`, starting at `startNode` and wrap-around at the end. + * + * @returns matching node or null + */ + findNextNode(match: string, startNode?: FancytreeNode): FancytreeNode; + + /** Find the next visible node that starts with `match`, starting at `startNode` and wrap-around at the end. + * + * @returns matching node or null + */ + findNextNode(match: (node: FancytreeNode) => boolean, startNode?: FancytreeNode): FancytreeNode; + + /** Find all nodes that matches condition. + * + * @returns array of nodes (may be empty) + */ + findAll(match: string | ((node: FancytreeNode) => boolean | undefined)): FancytreeNode[]; + + /** Generate INPUT elements that can be submitted with html forms. In selectMode 3 only the topmost selected nodes are considered. */ + generateFormElements(selected?: boolean, active?: boolean): void; + + /** Return the currently active node or null. */ + getActiveNode(): FancytreeNode; + + /** Return the first top level node if any (not the invisible root node). */ + getFirstChild(): FancytreeNode; + + /** Return node that has keyboard focus. + * + * @param ifTreeHasFocus (default: false) (not yet implemented) + */ + getFocusNode(ifTreeHasFocus?: boolean): FancytreeNode; + + /** Return node with a given key or null if not found. + * + * @param searchRoot (optional) only search below this node. + */ + getNodeByKey(key: string, searchRoot?: FancytreeNode): FancytreeNode; + + /** [ext-clones] Return all nodes with a given refKey (null if not found). + * + * @param rootNode optionally restrict results to descendants of this node. + */ + getNodesByRef(refKey: string, rootNode?: FancytreeNode): FancytreeNode[]; + + /** [ext-persist] Return persistence information from cookies Called like $("#tree").fancytree("getTree").getPersistData(); */ + getPersistData(): PersistData; + + /** Return the invisible system root node. */ + getRootNode(): FancytreeNode; + + /** Return an array of selected nodes. + * + * @param stopOnParents only return the topmost selected node (useful with selectMode 3) + */ + getSelectedNodes(stopOnParents?: boolean): FancytreeNode[]; + + /** Return true if the tree control has keyboard focus */ + hasFocus(): boolean; + + /** Write to browser console if debugLevel >= 1 (prepending tree name) */ + info(msg: any): void; + + /** [ext-edit] Check if any node in this tree in edit mode. */ + isEditing(): FancytreeNode; + + /** Make sure that a node with a given ID is loaded, by traversing - and loading - its parents. This method is ment for lazy hierarchies. A callback is executed for every node as we go. + * + * @param keyPathList one or more key paths (e.g. '/3/2_1/7') + * @param callback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error') + */ + loadKeyPath(keyPathList: string[], callback: (node: FancytreeNode, status: string) => void): JQueryPromise; + + /** Make sure that a node with a given ID is loaded, by traversing - and loading - its parents. This method is ment for lazy hierarchies. A callback is executed for every node as we go. + * + * @param keyPath a key path (e.g. '/3/2_1/7') + * @param callback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error') + */ + loadKeyPath(keyPath: string, callback: (node: FancytreeNode, status: string) => void): JQueryPromise; + + /** Re-fire beforeActivate and activate events. */ + reactivate(): void; + + /** Reload tree from source and return a promise. + * + * @param source optional new source (defaults to initial source data) + */ + reload(source?: any): JQueryPromise; + + /** Render tree (i.e. create DOM elements for all top-level nodes). + * + * @param force create DOM elements, even is parent is collapsed (default = false) + * @param deep (default = false) + */ + render(force?: boolean, deep?: boolean): void; + + /** @param flag (default = true) */ + setFocus(flag?: boolean): void; + + /** Return all nodes as nested list of NodeData. + * + * @param callback Called for every node + * @param includeRoot Returns the hidden system root node (and its children) (default = false) + */ + toDict(includeRoot?: boolean, callback?: (node: FancytreeNode) => void): any; + + /** Call fn(node) for all nodes. + * + * @param fn the callback function. Return false to stop iteration, return "skip" to skip this node and children only. + * @returns false, if the iterator was stopped. + */ + visit(fn: (node: FancytreeNode) => any): boolean; + + /** Write warning to browser console (prepending tree info) */ + warn(msg: any): void; + + /** Temporarily suppress rendering to improve performance on bulk-updates. + * + * @param {boolean} flag + * @returns {boolean} previous status + * @since 2.19 */ + enableUpdate(enabled: boolean): void; + } + + /** A FancytreeNode represents the hierarchical data model and operations. */ + interface FancytreeNode { + // #region Properties + /** The tree instance */ + tree: Fancytree; + /** The parent node */ + parent: FancytreeNode; + /** Node id (must be unique inside the tree) */ + key: string; + /** Display name (may contain HTML) */ + title: string; + /** Contains all extra data that was passed on node creation */ + data: any; + /** Array of child nodes. For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array to define a node that has no children. */ + children: FancytreeNode[]; + /** Use isExpanded(), setExpanded() to access this property. */ + expanded: boolean; + /** Addtional CSS classes, added to the node's ``. */ + extraClasses: string; + /** Folder nodes have different default icons and click behavior. Note: Also non-folders may have children. */ + folder: boolean; + /** Icon of the tree node. */ + icon: string; + /** null or type of temporarily generated system node like 'loading', or 'error'. */ + statusNodeType: string; + /** True if this node is loaded on demand, i.e. on first expansion. */ + lazy: boolean; + /** Alternative description used as hover banner */ + tooltip: string; + /** Outer element of single nodes */ + span: HTMLElement; + /** Outer element of single nodes for table extension */ + tr: HTMLTableRowElement; + unselectable?: boolean | undefined; + unselectableIgnore?: boolean | undefined; + unselectableStatus?: boolean | undefined; + + // #endregion + + // #region Methods + /** + * Append (or insert) a list of child nodes. + * + * @param children array of child node definitions (also single child accepted) + * @param insertBefore child node to insert nodes before. If omitted, the new children is appended. + * @returns The first child added. + */ + addChildren(children: Fancytree.NodeData[], insertBefore?: FancytreeNode): FancytreeNode; + /** + * Append (or insert) a list of child nodes. + * + * @param children array of child node definitions (also single child accepted) + * @param insertBefore key of the child node to insert nodes before. If omitted, the new children is appended. + * @returns The first child added. + */ + addChildren(children: Fancytree.NodeData[], insertBefore?: string): FancytreeNode; + /** + * Append (or insert) a list of child nodes. + * + * @param children array of child node definitions (also single child accepted) + * @param insertBefore index of the child node to insert nodes before. If omitted, the new children is appended. + * @returns The first child added. + */ + addChildren(children: Fancytree.NodeData[], insertBefore?: number): FancytreeNode; + /** + * Append (or insert) a single child node. + * + * @param child node to add + * @param insertBefore child node to insert this node before. If omitted, the new child is appended. + * @returns The child added. + */ + addChildren(child: Fancytree.NodeData, insertBefore?: FancytreeNode): FancytreeNode; + /** + * Append (or insert) a single child node. + * + * @param child node to add + * @param insertBefore key of the child node to insert this node before. If omitted, the new child is appended. + * @returns The child added. + */ + addChildren(child: Fancytree.NodeData, insertBefore?: string): FancytreeNode; + /** + * Append (or insert) a single child node. + * + * @param child node to add + * @param insertBefore index of the child node to insert this node before. If omitted, the new child is appended. + * @returns The child added. + */ + addChildren(child: Fancytree.NodeData, insertBefore?: number): FancytreeNode; + + /** Add class to node's span tag and to .extraClasses. + * @param className class name + */ + addClass(className: string): void; + + /** Append or prepend a node, or append a child node. This a convenience function that calls addChildren() + * + * @param mode 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child') (default='child') + * @returns new node. + */ + addNode(node: NodeData, mode?: string): FancytreeNode; + + /** Modify existing child nodes. */ + applyPatch(patch: NodePatch): JQueryPromise; + + /** Collapse all sibling nodes. */ + collapseSiblings(): JQueryPromise; + + /** Copy this node as sibling or child of `node`. + * + * @param node source node + * @param mode 'before' | 'after' | 'child' (default='child') + * @param map callback function(NodeData) that could modify the new node + * @returns new node. + */ + copyTo(node: FancytreeNode, mode?: string, map?: (node: NodeData) => void): FancytreeNode; + + /** Count direct and indirect children. + * + * @param deep pass 'false' to only count direct children. (default=true) + */ + countChildren(deep?: boolean): number; + + /** Write to browser console if debugLevel >= 2 (prepending node info) */ + debug(msg: any): void; + + /** [ext-edit] Create a new child or sibling node and start edit mode. + * + * @param mode 'before', 'after', or 'child' (default='child') + * @param init NodeData (or simple title string) + */ + editCreateNode(mode?: string, init?: Object): void; + + /** [ext-edit] Stop inline editing. + * + * @param applyChanges false: cancel edit, true: save (if modified) + */ + editEnd(applyChanges: boolean): void; + + /** [ext-edit] Start inline editing of current node title. */ + editStart(): void; + + /** Find all nodes that contain `match` in the title. + * + * @param match string to search for + */ + findAll(match: string): FancytreeNode[]; + + /** Find all nodes that contain `match` in the title. + * + * @param match a function that returns `true` if a node is matched. + */ + findAll(match: (node: FancytreeNode) => boolean): FancytreeNode[]; + + /** Find first node that contains `match` in the title (not including self). + * + * @param match string to search for + */ + findFirst(match: string): FancytreeNode; + + /** Find first node that contains `match` in the title (not including self). + * + * @param match a function that returns `true` if a node is matched. + */ + findFirst(match: (node: FancytreeNode) => boolean): FancytreeNode; + + /** Fix selection status, after this node was (de)selected in multi-hier mode. This includes (de)selecting all children. */ + fixSelection3AfterClick(): void; + + /** Fix selection status for multi-hier mode. Only end-nodes are considered to update the descendants branch and parents. Should be called after this node has loaded new children or after children have been modified using the API. */ + fixSelection3FromEndNodes(): void; + + /** Update node data. If dict contains 'children', then also replace the hole sub tree. */ + fromDict(dict: NodeData): void; + + /** Return the list of child nodes (undefined for unexpanded lazy nodes). */ + getChildren(): FancytreeNode[]; + + /** [ext-clones] Return a list of clone-nodes or null. */ + getCloneList(includeSelf?: boolean): FancytreeNode[]; + + /** Return the first child node or null. */ + getFirstChild(): FancytreeNode; + + /** Return the 0-based child index. */ + getIndex(): number; + + /** Return the hierarchical child index (1-based, e.g. '3.2.4'). */ + getIndexHier(): string; + + /** Return the parent keys separated by options.keyPathSeparator, e.g. "id_1/id_17/id_32". */ + getKeyPath(excludeSelf: boolean): string; + + /** Return the last child of this node or null. */ + getLastChild(): FancytreeNode; + + /** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... . */ + getLevel(): number; + + /** Return the successor node (under the same parent) or null. */ + getNextSibling(): FancytreeNode; + + /** Return the parent node (null for the system root node). */ + getParent(): FancytreeNode; + + /** Return an array of all parent nodes (top-down). + * + * @param includeRoot Include the invisible system root node. (default=false) + * @param includeSelf Include the node itself (default=false). + */ + getParentList(includeRoot: boolean, includeSelf: boolean): FancytreeNode[]; + + /** Return the predecessor node (under the same parent) or null. */ + getPrevSibling(): FancytreeNode; + + /** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded). */ + hasChildren(): boolean; + + /** Return true if node has keyboard focus. */ + hasFocus(): boolean; + + /** Write to browser console if debugLevel >= 1 (prepending node info) */ + info(msg: string): void; + + /** Return true if node is active (see also FancytreeNode.isSelected). */ + isActive(): boolean; + + /** Return true if node is a direct child of otherNode. */ + isChildOf(otherNode: FancytreeNode): boolean; + + /** [ext-clones] Return true if this node has at least another clone with same refKey. */ + isClone(): boolean; + + /** Return true, if node is a direct or indirect sub node of otherNode. */ + isDescendantOf(otherNode: FancytreeNode): boolean; + + /** [ext-edit] Check if this node is in edit mode. */ + isEditing(): boolean; + + /** Return true if node is expanded. */ + isExpanded(): boolean; + + /** Return true if node is the first node of its parent's children. */ + isFirstSibling(): boolean; + + /** Return true if node is a folder, i.e. has the node.folder attribute set. */ + isFolder(): boolean; + + /** Return true if node is the last node of its parent's children. */ + isLastSibling(): boolean; + + /** Return true if node is lazy (even if data was already loaded) */ + isLazy(): boolean; + + /** Return true if node is lazy and loaded. For non-lazy nodes always return true. */ + isLoaded(): boolean; + + /**Return true if children are currently beeing loaded, i.e. a Ajax request is pending. */ + isLoading(): boolean; + + /** Return true if this is the (invisible) system root node. */ + isRootNode(): boolean; + + /** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive). */ + isSelected(): boolean; + + /** Return true if this node is a temporarily generated system node like 'loading', or 'error' (node.statusNodeType contains the type). */ + isStatusNode(): boolean; + + /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node. */ + isTopLevel(): boolean; + + /** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false. */ + isUndefined(): boolean; + + /** Return true if all parent nodes are expanded. Note: this does not check whether the node is scrolled into the visible part of the screen. */ + isVisible(): boolean; + + /** Load all children of a lazy node if neccessary. The *expanded* state is maintained. + * + * @param forceReload Pass true to discard any existing nodes before. + */ + load(forceReload?: boolean): JQueryPromise; + + /** Expand all parents and optionally scroll into visible area as neccessary. Promise is resolved, when lazy loading and animations are done. + * + * @param opts passed to `setExpanded()`. Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true} + */ + makeVisible(opts?: Object): JQueryPromise; + + /** Move this node to targetNode. + * + * @param mode 'child': append this node as last child of targetNode. + * This is the default. To be compatble with the D'n'd + * hitMode, we also accept 'over'. + * 'before': add this node as sibling before targetNode. + * 'after': add this node as sibling after targetNode. + * + * @param map optional callback(FancytreeNode) to allow modifcations + */ + moveTo(targetNode: FancytreeNode, mode: string, map?: (node: FancytreeNode) => void): void; + + /** Set focus relative to this node and optionally activate. + * + * @param where The keyCode that would normally trigger this move, e.g. `$.ui.keyCode.LEFT` would collapse the node if it is expanded or move to the parent oterwise. + * @param activate (default=true) + */ + navigate(where: number, activate?: boolean): JQueryPromise; + + /** Remove this node (not allowed for system root). */ + remove(): void; + + /** Remove childNode from list of direct children. */ + removeChild(childNode: FancytreeNode): void; + + /** Remove all child nodes and descendents. This converts the node into a leaf. + * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy() in order to trigger lazyLoad on next expand. + */ + removeChildren(): void; + + /** Remove class from node's span tag and .extraClasses. + * @param className class name + */ + removeClass(className: string): void; + + /** This method renders and updates all HTML markup that is required to display this node in its current state. + * + * @param force re-render, even if html markup was already created + * @param deep also render all descendants, even if parent is collapsed + */ + render(force?: boolean, deep?: boolean): void; + + /** Update element's CSS classes according to node state. */ + renderStatus(): void; + + /** Create HTML markup for the node's outer (expander, checkbox, icon, and title). */ + renderTitle(): void; + + /** [ext-clones] Update key and/or refKey for an existing node. */ + reRegister(key: string, refKey: string): boolean; + + /** Remove all children, collapse, and set the lazy-flag, so that the lazyLoad event is triggered on next expand. */ + resetLazy(): void; + + /** Schedule activity for delayed execution (cancel any pending request). scheduleAction('cancel') will only cancel a pending request (if any). */ + scheduleAction(mode: string, ms: number): void; + + /** + * @param effects animation options. + * @param options {topNode: null, effects: ..., parent: ...} this node will remain visible in any case, even if `this` is outside the scroll pane. + */ + scrollIntoView(effects?: boolean, options?: Object): JQueryPromise; + + /** + * @param effects animation options. + * @param options {topNode: null, effects: ..., parent: ...} this node will remain visible in any case, even if `this` is outside the scroll pane. + */ + scrollIntoView(effects?: Object, options?: Object): JQueryPromise; + + /** + * @param flag pass false to deactivate + * @param opts additional options. Defaults to {noEvents: false} + */ + setActive(flag?: boolean, opts?: Object): JQueryPromise; + + /** + * @param flag pass false to collapse. + * @param opts additional options. Defaults to {noAnimation:false, noEvents:false} + */ + setExpanded(flag?: boolean, opts?: Object): JQueryPromise; + + /** + * Set keyboard focus to this node. + * + * @param flag pass false to blur. + */ + setFocus(flag?: boolean): void; + + /** + * Select this node, i.e. check the checkbox. + * + * @param flag pass false to deselect. + */ + setSelected(flag?: boolean): void; + + /** + * Mark a lazy node as 'error', 'loading', or 'ok'. + * + * @param status 'error', 'ok' + */ + setStatus(status: string, message?: string, details?: string): void; + + /** Rename this node. */ + setTitle(title: string): void; + + /** + * Sort child list by title. + * + * @param cmp custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title). + * @param deep pass true to sort all descendant nodes + */ + sortChildren(cmp?: (a: FancytreeNode, b: FancytreeNode) => number, deep?: boolean): void; + + /** + * Convert node (or whole branch) into a plain object. The result is compatible with node.addChildren(). + * + * @param recursive include child nodes. + * @param callback callback(dict) is called for every node, in order to allow modifications + */ + toDict(recursive?: boolean, callback?: (dict: NodeData) => void): NodeData; + + /** Set, clear, or toggle class of node's span tag and .extraClasses. + * @param {string} className class name (separate multiple classes by space) + * @param {boolean} [flag] true/false to add/remove class. If omitted, class is toggled. + * @return true if a class was added + */ + toggleClass(className: string, flag?: boolean): boolean; + + /** Flip expanded status. */ + toggleExpanded(): void; + + /** Flip selection status. */ + toggleSelected(): void; + + /** + * Call fn(node) for all child nodes. + * Stop iteration, if fn() returns false. Skip current branch, + * if fn() returns "skip". Return false if iteration was stopped. + * + * @param fn the callback function. Return false to stop iteration, return "skip" to skip this node and its children only. + * @param includeSelf (default=false) + */ + visit(fn: (node: FancytreeNode) => any, includeSelf?: boolean): boolean; + + /** + * Call fn(node) for all child nodes and recursively load lazy children. + * Note: If you need this method, you probably should consider to review your architecture! Recursivley loading nodes is + * a perfect way for lazy programmers to flood the server with requests ;-) + * + * @param fn the callback function. Return false to stop iteration, return "skip" to skip this node and its children only. + * @param includeSelf (default=false) + */ + visitAndLoad(fn: (node: FancytreeNode) => any, includeSelf?: boolean): JQueryPromise; + + /** + * Call fn(node) for all parent nodes, bottom-up, including invisible system root. + * Stop iteration, if fn() returns false. + * Return false if iteration was stopped. + * + * @param fn the callback function. Return false to stop iteration, return "skip" to skip this node and its children only. + * @param includeSelf (default=false) + */ + visitParents(fn: (node: FancytreeNode) => any, includeSelf?: boolean): boolean; + + /** + * Write warning to browser console (prepending node info) + */ + warn(msg: any): void; + // #endregion + } + + enum FancytreeClickFolderMode { + activate = 1, + expand = 2, + activate_and_expand = 3, + activate_dblclick_expands = 4, + } + + enum FancytreeSelectMode { + single = 1, + multi = 2, + mutlti_hier = 3, + } + + /** Context object passed to events and hook functions. */ + interface EventData { + /** The tree instance */ + tree: Fancytree; + /** The jQuery UI tree widget */ + widget: any; // JQueryUI.Widget; + /** Shortcut to tree.options */ + options: FancytreeOptions; + /** The jQuery Event that initially triggered this call */ + originalEvent: JQueryEventObject; + /** The node that this call applies to (`null` for tree events) */ + node: FancytreeNode; + /** (output parameter) Event handlers can return values back to the + * caller. Used by `lazyLoad`, `postProcess`, ... */ + result: any; + /** (only for click and dblclick events) 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' */ + targetType: string; + /** (only for postProcess event) Original ajax response */ + response: any; + } + + /** The `this` context of any event function is set to tree's the HTMLDivElement */ + interface FancytreeEvents { + /** 'data.node' was deactivated. */ + activate?(event: JQueryEventObject, data: EventData): void; + /** Return false to prevent default processing */ + beforeActivate?(event: JQueryEventObject, data: EventData): boolean; + /** Return `false` to prevent default processing */ + beforeExpand?(event: JQueryEventObject, data: EventData): boolean; + /** Return `false` to prevent default processing */ + beforeSelect?(event: JQueryEventObject, data: EventData): boolean; + /** `data.node` lost keyboard focus */ + blur?(event: JQueryEventObject, data: EventData): void; + /** `data.tree` lost keyboard focus */ + blurTree?(event: JQueryEventObject, data: EventData): void; + /** `data.node` was clicked. `data.targetType` contains the region ("title", "expander", ...). Return `false` to prevent default processing, i.e. activating, etc. */ + click?(event: JQueryEventObject, data: EventData): boolean; + /** `data.node` was collapsed */ + collapse?(event: JQueryEventObject, data: EventData): void; + /** Widget was created (called only once, even if re-initialized). */ + create?(event: JQueryEventObject, data: EventData): void; + /** Allow tweaking and binding, after node was created for the first time (NOTE: this event is only available as callback, but not for bind()) */ + createNode?(event: JQueryEventObject, data: EventData): void; + /** `data.node` was double-clicked. `data.targetType` contains the region ("title", "expander", ...). Return `false` to prevent default processing, i.e. expanding, etc. */ + dblclick?(event: JQueryEventObject, data: EventData): boolean; + /** `data.node` was deactivated */ + deactivate?(event: JQueryEventObject, data: EventData): void; + /** `data.node` was expanded */ + expand?(event: JQueryEventObject, data: EventData): void; + /** `data.node` received keyboard focus */ + focus?(event: JQueryEventObject, data: EventData): void; + /**`data.tree` received keyboard focus */ + focusTree?(event: JQueryEventObject, data: EventData): void; + /** Widget was (re-)initialized. */ + init?(event: JQueryEventObject, data: EventData): void; + /** `data.node` received key. `event.which` contains the key. Return `false` to prevent default processing, i.e. navigation. Call `data.result = "preventNav";` to prevent navigation but still allow default handling inside embedded input controls. */ + keydown?(event: JQueryEventObject, data: EventData): boolean; + /** (currently unused) */ + keypress?(event: JQueryEventObject, data: EventData): void; + /** `data.node` is a lazy node that is expanded for the first time. The new child data must be returned in the `data.result` property (see `source` option for available formats). */ + lazyLoad?(event: JQueryEventObject, data: EventData): void; + /** Node data was loaded, i.e. `node.nodeLoadChildren()` finished */ + loadChildren?(event: JQueryEventObject, data: EventData): void; + /** A load error occured. Return `false` to prevent default processing. */ + loadError?(event: JQueryEventObject, data: EventData): boolean; + /** Allows to modify the ajax response. */ + postProcess?(event: JQueryEventObject, data: EventData): void; + /** `data.node` was removed (NOTE: this event is only available as callback, but not for bind()) */ + removeNode?(event: JQueryEventObject, data: EventData): void; + /** (used by table extension) */ + renderColumns?(event: JQueryEventObject, data: EventData): void; + /** Allow tweaking after node state was rendered (NOTE: this event is only available as callback, but not for bind()) */ + renderNode?(event: JQueryEventObject, data: EventData): void; + /** Allow replacing the `` markup (NOTE: this event is only available as callback, but not for bind()) */ + renderTitle?(event: JQueryEventObject, data: EventData): void; + /** ext-persist has expanded, selected, and activated the previous state */ + restore?(event: JQueryEventObject, data: EventData): void; + /** `data.node` was selected */ + select?(event: JQueryEventObject, data: EventData): void; + /** Enable RTL version, default is false */ + rtl?: boolean | undefined; + } + + interface FancytreeOptions extends FancytreeEvents { + /** Make sure that the active node is always visible, i.e. its parents are expanded (default: true). */ + activeVisible?: boolean | undefined; + /** Default options for ajax requests. */ + ajax?: { + /** + * HTTP Method (default: 'GET') + */ + type: string; + /** + * false: Append random '_' argument to the request url to prevent caching. + */ + cache: boolean; + /** + * Default 'json' -> Expect json format and pass json object to callbacks. + */ + dataType: string; + } | undefined; + /** (default: false) Add WAI-ARIA attributes to markup */ + aria?: boolean | undefined; + /** Activate a node when focused with the keyboard (default: true) */ + autoActivate?: boolean | undefined; + /** Automatically collapse all siblings, when a node is expanded (default: false). */ + autoCollapse?: boolean | undefined; + /** Scroll node into visible area, when focused by keyboard (default: false). */ + autoScroll?: boolean | undefined; + /** Display checkboxes to allow selection (default: false) */ + checkbox?: boolean | string | ((event: JQueryEventObject, data: EventData) => boolean) | undefined; + /** Defines what happens, when the user click a folder node. (default: activate_dblclick_expands) */ + clickFolderMode?: FancytreeClickFolderMode | undefined; + /** 0..4 (null: use global setting $.ui.fancytree.debugInfo) */ + debugLevel?: 0 | 1 | 2 | 3 | 4 | undefined; + /** callback(node) is called for new nodes without a key. Must return a new unique key. (default null: generates default keys like that: "_" + counter) */ + defaultKey?: ((node: FancytreeNode) => string) | undefined; + /** Accept passing ajax data in a property named `d` (default: true). */ + enableAspx?: boolean | undefined; + /** Enable titles (default: false) */ + enableTitles?: boolean | undefined; + /** List of active extensions (default: []) */ + extensions?: Array | undefined; + /** Set focus when node is checked by a mouse click (default: false) */ + focusOnSelect?: boolean | undefined; + /** Add `id="..."` to node markup (default: true). */ + generateIds?: boolean | undefined; + /** Node icon url, if only filename, please use imagePath to set the path */ + icon?: boolean | string | undefined; + /** Prefix (default: "ft_") */ + idPrefix?: string | undefined; + /** Path to a folder containing icons (default: null, using 'skin/' subdirectory). */ + imagePath?: string | undefined; + /** Support keyboard navigation (default: true). */ + keyboard?: boolean | undefined; + /** (default: "/") */ + keyPathSeparator?: string | undefined; + /** 2: top-level nodes are not collapsible (default: 1) */ + minExpandLevel?: number | undefined; + /** navigate to next node by typing the first letters (default: false) */ + quicksearch?: boolean | undefined; + /** Right to left mode (default: false) */ + rtl?: boolean | undefined; + /** optional margins for node.scrollIntoView() (default: {top: 0, bottom: 0}) */ + scrollOfs?: { top: number; bottom: number } | undefined; + /** scrollable container for node.scrollIntoView() (default: $container) */ + scrollParent?: JQuery | null | undefined; + /** default: multi_hier */ + selectMode?: FancytreeSelectMode | undefined; + /** Used to Initialize the tree. */ + source?: any[] | any | undefined; + /** Translation table */ + strings?: TranslationTable | undefined; + /** Add tabindex='0' to container, so tree can be reached using TAB */ + tabbable?: boolean | undefined; + /** Add tabindex='0' to node title span, so it can receive keyboard focus */ + titlesTabbable?: boolean | undefined; + /** Animation options, false:off (default: { effect: "blind", options: {direction: "vertical", scale: "box"}, duration: 200 }) */ + toggleEffect?: any; + /** Tooltips */ + tooltip?: boolean | undefined; + + /** (dynamic Option)Prevent (de-)selection using mouse or keyboard. */ + unselectable?: + | boolean + | ((event: JQueryEventObject, data: Fancytree.EventData) => boolean | undefined) + | undefined; + /** (dynamic Option)Ignore this node when calculating the partsel status of parent nodes in selectMode 3 propagation. */ + unselectableIgnore?: + | boolean + | ((event: JQueryEventObject, data: Fancytree.EventData) => boolean | undefined) + | undefined; + /** (dynamic Option)Use this as constant selected value (overriding selectMode 3 propagation). */ + unselectableStatus?: + | boolean + | ((event: JQueryEventObject, data: Fancytree.EventData) => boolean | undefined) + | undefined; + + //////////////// + // EXTENSIONS // + //////////////// + dnd5?: Extensions.DragAndDrop5 | undefined; + filter?: Extensions.Filter | undefined; + table?: Extensions.Table | undefined; + + /** Options for misc extensions - see docs for typings */ + [extension: string]: any; + } + + interface TranslationTable { + /** + * "Loading..." // … would be escaped when escapeTitles is true + */ + loading?: string | undefined; + /** + * "Load error!" + */ + loadError?: string | undefined; + /** + * "More..." + */ + moreData?: string | undefined; + /** + * "No data." + */ + noData?: string | undefined; + } + + interface PersistData { + active: string | null; + expanded: string[]; + focus: string | null; + selected: string[]; + } + + namespace Extensions { + interface List { + dnd5?: DragAndDrop5 | undefined; + filter?: Filter | undefined; + table?: Table | undefined; + [extension: string]: any; + } + + interface DragAndDrop5 { + /** + * Expand nodes after n milliseconds of hovering. + */ + autoExpandMS?: number | undefined; + /** + * Absolute position offset for .fancytree-drop-marker + */ + dropMarkerOffsetX?: number | undefined; + /** + * Additional offset for drop-marker with hitMode = "before"/"after" + */ + dropMarkerInsertOffsetX?: number | undefined; + /** + * true: Drag multiple (i.e. selected) nodes. + */ + multiSource?: boolean | undefined; + /** + * Prevent dropping nodes from different Fancytrees + */ + preventForeignNodes?: boolean | undefined; + /** + * Prevent dropping items other than Fancytree nodes + */ + preventNonNodes?: boolean | undefined; + /** + * Prevent dropping nodes on own descendants + */ + preventRecursiveMoves?: boolean | undefined; + /** + * Prevent dropping nodes 'before self', etc. + */ + preventVoidMoves?: boolean | undefined; + /** + * Enable auto-scrolling while dragging + */ + scroll?: boolean | undefined; + /** + * Active top/bottom margin in pixel + */ + scrollSensitivity?: number | undefined; + /** + * Pixel per event + */ + scrollSpeed?: number | undefined; + /** + * Allow dragging of nodes to different IE windows, default: false + */ + setTextTypeJson?: boolean | undefined; + /** + * Callback(sourceNode, data), return true, to enable dnd drag + */ + dragStart?: ((sourceNode: FancytreeNode, data: any) => void) | undefined; + dragDrag?: ((sourceNode: FancytreeNode, data: any) => void) | undefined; + dragEnd?: ((sourceNode: FancytreeNode, data: any) => void) | undefined; + /** + * Callback(targetNode, data), return true, to enable dnd drop + */ + dragEnter?: ((targetNode: FancytreeNode, data: any) => void) | undefined; + /** + * Events (drag over) + */ + dragOver?: ((targetNode: FancytreeNode, data: any) => void) | undefined; + /** + * Callback(targetNode, data), return false to prevent autoExpand + */ + dragExpand?: ((targetNode: FancytreeNode, data: any) => void) | undefined; + /** + * Events (drag drop) + */ + dragDrop?: ((node: FancytreeNode, data: any) => void) | undefined; + dragLeave?: ((targetNode: FancytreeNode, data: any) => void) | undefined; + /** + * Support misc options + */ + [key: string]: any; + } + /** + * Define filter-extension options + */ + interface Filter { + /** + * Re-apply last filter if lazy data is loaded + */ + autoApply?: boolean | undefined; + /** + * Expand all branches that contain matches while filtered + */ + autoExpand?: boolean | undefined; + /** + * Show a badge with number of matching child nodes near parent icons + */ + counter?: boolean | undefined; + /** + * Match single characters in order, e.g. 'fb' will match 'FooBar' + */ + fuzzy?: boolean | undefined; + /** + * Hide counter badge if parent is expanded + */ + hideExpandedCounter?: boolean | undefined; + /** + * Hide expanders if all child nodes are hidden by filter + */ + hideExpanders?: boolean | undefined; + /** + * Highlight matches by wrapping inside tags + */ + highlight?: boolean | undefined; + /** + * Match end nodes only + */ + leavesOnly?: boolean | undefined; + /** + * Display a 'no data' status node if result is empty + */ + nodata?: boolean | undefined; + /** + * Grayout unmatched nodes (pass "hide" to remove unmatched node instead); default 'dimm' + */ + mode?: "dimm" | "hide" | undefined; + /** + * Support misc options + */ + [key: string]: any; + } + /** + * Define table-extension options + */ + interface Table { + /** + * Render the checkboxes into the this column index (default: nodeColumnIdx) + */ + checkboxColumnIdx: any; + /** + * Indent every node level by 16px; default: 16 + */ + indentation: number; + /** + * Render node expander, icon, and title to this column (default: 0) + */ + nodeColumnIdx: number; + /** + * Support misc options + */ + [key: string]: any; + } + } + + /** Data object passed to FancytreeNode() constructor. Note: typically these attributes are accessed by meber methods, e.g. `node.isExpanded()` and `node.setSelected(false)`. */ + interface NodeData { + /** node text (may contain HTML tags) */ + title: string; + icon?: boolean | string | undefined; + /** unique key for this node (auto-generated if omitted) */ + key?: string | undefined; + /** (reserved) */ + refKey?: string | undefined; + expanded?: boolean | undefined; + /** (initialization only, but will not be stored with the node). */ + active?: boolean | undefined; + /** (initialization only, but will not be stored with the node). */ + focus?: boolean | undefined; + folder?: boolean | undefined; + hideCheckbox?: boolean | undefined; + lazy?: boolean | undefined; + selected?: boolean | undefined; + unselectable?: boolean | undefined; + /** optional array of child nodes */ + children?: NodeData[] | undefined; + tooltip?: string | undefined; + /** class names added to the node markup (separate with space) */ + extraClasses?: string | undefined; + /** all properties from will be copied to `node.data` */ + data?: Object | undefined; + + /** Will be added as title attribute of the node's icon span,thus enabling a tooltip. */ + iconTooltip?: string | undefined; + + /** If set, make this node a status node. Values: 'error', 'loading', 'nodata', 'paging'. */ + statusNodeType?: string | undefined; + + /** Made available as node.type. */ + type?: string | undefined; + + /** Ignore this node when calculating the partsel status of parent nodes in selectMode 3 propagation. */ + unselectableIgnore?: boolean | undefined; + + /** Use this as constant selected value(overriding selectMode 3 propagation). */ + unselectableStatus?: boolean | undefined; + } + + /** Data object similar to NodeData, but with additional options. + * May be passed to FancytreeNode#applyPatch (Every property that is omitted (or set to undefined) will be ignored) */ + interface NodePatch { + /** (not yet implemented) */ + appendChildren?: NodeData | undefined; + /** (not yet implemented) */ + replaceChildren?: NodeData | undefined; + /** (not yet implemented) */ + insertChildren?: NodeData | undefined; + } + + /** May be passed to Fancytree#applyPatch. */ + interface TreePatch { + [key: string]: NodePatch; + } + + interface FancytreeStatic { + buildType: string; + debugLevel: number; + version: string; + + /** Throw an error if condition fails (debug method). */ + assert(cond: boolean, msg: string): void; + + /** Return a function that executes *fn* at most every *timeout* ms. */ + debounce void>(timeout: number, fn: T, invokeAsap?: boolean, ctx?: any): T; + + debug(msg: string): void; + + error(msg: string): void; + + escapeHtml(s: string): string; + + getEventTarget(event: Event): Object; + + getEventTargetType(event: Event): string; + + getNode(el: JQuery): FancytreeNode; + getNode(el: Event): FancytreeNode; + getNode(el: Element): FancytreeNode; + + getTree(el: Element | JQuery | Event | number | string): Fancytree; + + info(msg: string): void; + + /** Convert a keydown event to a string like 'ctrl+a', 'ctrl+shift+f2'. */ + keyEventToString(event: Event): string; + + /** Parse tree data from HTML markup */ + parseHtml($ul: JQuery): NodeData[]; + + /** Add Fancytree extension definition to the list of globally available extensions. */ + registerExtension(definition: Object): void; + + unescapeHtml(s: string): string; + + warn(msg: string): void; + } +} +//#endregion From 23d01ec351137bac93eb02eb7537021995ac58ab Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 24 Feb 2025 21:35:35 +0200 Subject: [PATCH 5/5] fix(build): type definitions for context menu --- src/public/app/menus/tree_context_menu.ts | 4 +++- src/public/app/services/note_types.ts | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/public/app/menus/tree_context_menu.ts b/src/public/app/menus/tree_context_menu.ts index 96872b484..5c2c74fe9 100644 --- a/src/public/app/menus/tree_context_menu.ts +++ b/src/public/app/menus/tree_context_menu.ts @@ -18,7 +18,9 @@ interface ConvertToAttachmentResponse { attachment?: FAttachment; } -type TreeCommandNames = FilteredCommandNames; +// This will include all commands that implement ContextMenuCommandData, but it will not work if it additional options are added via the `|` operator, +// so they need to be added manually. +export type TreeCommandNames = FilteredCommandNames | "openBulkActionsDialog"; export default class TreeContextMenu implements SelectMenuItemEventListener { private treeWidget: NoteTreeWidget; diff --git a/src/public/app/services/note_types.ts b/src/public/app/services/note_types.ts index fc6e7bed6..9c6af3b5c 100644 --- a/src/public/app/services/note_types.ts +++ b/src/public/app/services/note_types.ts @@ -2,12 +2,10 @@ import server from "./server.js"; import froca from "./froca.js"; import { t } from "./i18n.js"; import type { MenuItem } from "../menus/context_menu.js"; -import type { ContextMenuCommandData, FilteredCommandNames } from "../components/app_context.js"; +import type { TreeCommandNames } from "../menus/tree_context_menu.js"; -type NoteTypeCommandNames = FilteredCommandNames; - -async function getNoteTypeItems(command?: NoteTypeCommandNames) { - const items: MenuItem[] = [ +async function getNoteTypeItems(command?: TreeCommandNames) { + const items: MenuItem[] = [ { title: t("note_types.text"), command, type: "text", uiIcon: "bx bx-note" }, { title: t("note_types.code"), command, type: "code", uiIcon: "bx bx-code" }, { title: t("note_types.saved-search"), command, type: "search", uiIcon: "bx bx-file-find" },