From 28c8ccb44bcf6d2a49684c7ab197d31fe045625c Mon Sep 17 00:00:00 2001 From: Andrew Beal Date: Mon, 20 Apr 2026 20:20:22 +0100 Subject: [PATCH] feat: add quick actions system with provider-aware model settings Introduce QuickActionsService and QuickAgent for lightweight, single-shot AI operations. Add a dedicated quickActionModel setting alongside a new top-level provider setting, with validation ensuring all models match the selected provider and provider-specific defaults. Refactor FileSystemService to offer both TFile and path-based overloads (readFile/readFilePath, writeToFile/writeToFilePath, patchFile/patchFileAtPath). Replace window/document globals with activeWindow/ activeDocument throughout InputService and VaultkeeperAISettingTab for Obsidian mobile compatibility. Update linting packages to latest. --- AIClasses/BaseAIClass.ts | 2 + AIClasses/Claude/Claude.ts | 2 +- AIClasses/Gemini/Gemini.ts | 4 +- AIClasses/Mistral/Mistral.ts | 2 +- AIClasses/OpenAI/OpenAI.ts | 2 +- AIClasses/ToolDefinitions/Tools/SubmitPlan.ts | 2 +- AIPrompts/IPrompt.ts | 2 +- AIPrompts/QuickActionPrompts/Beautify.ts | 7 + Enums/AITool.ts | 2 +- Enums/AgentType.ts | 3 +- Enums/ApiProvider.ts | 33 +- Enums/Copy.ts | 2 + Helpers/Helpers.ts | 2 +- Helpers/StringTools.ts | 2 +- Services/AIServices/AIToolService.ts | 6 +- Services/AIServices/QuickAgent.ts | 55 + Services/ChatService.ts | 2 +- Services/FileSystemService.ts | 20 +- Services/HTMLService.ts | 4 +- Services/InputService.ts | 22 +- Services/MemoriesService.ts | 4 +- Services/QuickActionsService.ts | 84 + Services/ServiceRegistration.ts | 4 + Services/Services.ts | 2 + Services/SettingsService.ts | 41 +- Services/StreamingMarkdownService.ts | 8 +- Services/WebViewerService.ts | 2 +- Types/ApiError.ts | 2 +- Views/VaultkeeperAISettingTab.ts | 99 +- __tests__/Services/FileSystemService.test.ts | 34 +- __tests__/Services/SettingsService.test.ts | 24 +- .../VaultCacheService.performance.test.ts | 6 +- __tests__/Services/VaultService.pdf.test.ts | 6 +- .../Services/VaultService.performance.test.ts | 6 +- __tests__/Services/VaultService.test.ts | 6 +- eslint.config.js | 120 +- main.ts | 6 +- package-lock.json | 1603 ++++++++++++----- package.json | 12 +- 39 files changed, 1562 insertions(+), 683 deletions(-) create mode 100644 AIPrompts/QuickActionPrompts/Beautify.ts create mode 100644 Services/AIServices/QuickAgent.ts create mode 100644 Services/QuickActionsService.ts diff --git a/AIClasses/BaseAIClass.ts b/AIClasses/BaseAIClass.ts index 10e103f..d381f05 100644 --- a/AIClasses/BaseAIClass.ts +++ b/AIClasses/BaseAIClass.ts @@ -104,6 +104,8 @@ export abstract class BaseAIClass implements IAIClass { return this.settingsService.settings.planningModel; case AgentType.Execution: return this.settingsService.settings.model; + case AgentType.QuickAction: + return this.settingsService.settings.quickActionModel; } } diff --git a/AIClasses/Claude/Claude.ts b/AIClasses/Claude/Claude.ts index 5657cc2..4cee7b8 100644 --- a/AIClasses/Claude/Claude.ts +++ b/AIClasses/Claude/Claude.ts @@ -138,7 +138,7 @@ export class Claude extends BaseAIClass { const args = JSON.parse(this.accumulatedFunctionArgs) as Record; toolCall = new AIToolCall( aiToolFromString(this.accumulatedFunctionName), - args as Record, + args, this.accumulatedFunctionId || undefined, undefined // thoughtSignature not used by Claude ); diff --git a/AIClasses/Gemini/Gemini.ts b/AIClasses/Gemini/Gemini.ts index 7f1de82..ea8969e 100644 --- a/AIClasses/Gemini/Gemini.ts +++ b/AIClasses/Gemini/Gemini.ts @@ -190,7 +190,7 @@ export class Gemini extends BaseAIClass { if (isComplete && this.accumulatedFunctionName) { toolCall = new AIToolCall( aiToolFromString(this.accumulatedFunctionName), - this.accumulatedFunctionArgs as Record, + this.accumulatedFunctionArgs, undefined, // toolId not used by Gemini this.accumulatedThoughtSignature || undefined ); @@ -419,7 +419,7 @@ export class Gemini extends BaseAIClass { // Handle object format: { seconds: 10, nanos: 500000000 } if (typeof rawDelay === 'object' && rawDelay !== null && 'seconds' in rawDelay) { - const seconds = (rawDelay as { seconds: unknown }).seconds; + const seconds = (rawDelay).seconds; if (typeof seconds === 'number' || typeof seconds === 'string') { return Math.ceil(Number(seconds)); } diff --git a/AIClasses/Mistral/Mistral.ts b/AIClasses/Mistral/Mistral.ts index 6cc7474..964c332 100644 --- a/AIClasses/Mistral/Mistral.ts +++ b/AIClasses/Mistral/Mistral.ts @@ -168,7 +168,7 @@ export class Mistral extends BaseAIClass { const args = JSON.parse(firstToolCall.args) as Record; toolCall = new AIToolCall( aiToolFromString(firstToolCall.name), - args as Record, + args, firstToolCall.id || undefined, undefined ); diff --git a/AIClasses/OpenAI/OpenAI.ts b/AIClasses/OpenAI/OpenAI.ts index e5352e0..251f419 100644 --- a/AIClasses/OpenAI/OpenAI.ts +++ b/AIClasses/OpenAI/OpenAI.ts @@ -164,7 +164,7 @@ export class OpenAI extends BaseAIClass { const args = JSON.parse(itemDoneEvent.item.arguments) as Record; toolCall = new AIToolCall( aiToolFromString(itemDoneEvent.item.name), - args as Record, + args, itemDoneEvent.item.call_id || itemDoneEvent.item_id, undefined // thoughtSignature not used by OpenAI ); diff --git a/AIClasses/ToolDefinitions/Tools/SubmitPlan.ts b/AIClasses/ToolDefinitions/Tools/SubmitPlan.ts index b522430..99711b3 100644 --- a/AIClasses/ToolDefinitions/Tools/SubmitPlan.ts +++ b/AIClasses/ToolDefinitions/Tools/SubmitPlan.ts @@ -26,7 +26,7 @@ Do NOT use this function: properties: { description: { type: "string", - description: "Brief summary of what this step accomplishes (e.g., 'Search for ML notes', 'Create index file'). This is user-facing and should be concise." + description: "Brief summary of what this step accomplishes (e.g., 'Search for ML notes', 'Create index file'). This is user-facing and should be very concise." }, instruction: { type: "string", diff --git a/AIPrompts/IPrompt.ts b/AIPrompts/IPrompt.ts index 2df2aa7..d36c049 100644 --- a/AIPrompts/IPrompt.ts +++ b/AIPrompts/IPrompt.ts @@ -82,7 +82,7 @@ export class AIPrompt implements IPrompt { } public async userInstruction(): Promise { - const result = await this.fileSystemService.readFile(this.settingsService.settings.userInstruction, true); + const result = await this.fileSystemService.readFilePath(this.settingsService.settings.userInstruction, true); return result instanceof Error ? "" : result; } } \ No newline at end of file diff --git a/AIPrompts/QuickActionPrompts/Beautify.ts b/AIPrompts/QuickActionPrompts/Beautify.ts new file mode 100644 index 0000000..dfc0b19 --- /dev/null +++ b/AIPrompts/QuickActionPrompts/Beautify.ts @@ -0,0 +1,7 @@ +export const BeautifyPrompt: string = `You are a writing editor. Your task is to beautify the provided text. + +Improve clarity, flow, and readability while preserving the author's voice and meaning. Fix grammar and awkward phrasing. +Use Markdown formatting (headings, bold, italics, lists, blockquotes) where it enhances structure and readability in Obsidian. +Do not add new ideas, remove content, or change the structure unless it clearly improves readability. + +Return only the improved text with no explanation, preamble, or commentary.`; \ No newline at end of file diff --git a/Enums/AITool.ts b/Enums/AITool.ts index 8c3ea73..4661629 100644 --- a/Enums/AITool.ts +++ b/Enums/AITool.ts @@ -36,7 +36,7 @@ export enum AITool { export function fromString(functionName: string): AITool { const enumValue = Object.values(AITool).find((value: string) => value === functionName); if (enumValue) { - return enumValue as AITool; + return enumValue; } return AITool.Unknown; } diff --git a/Enums/AgentType.ts b/Enums/AgentType.ts index c334af3..b701dbb 100644 --- a/Enums/AgentType.ts +++ b/Enums/AgentType.ts @@ -2,5 +2,6 @@ export enum AgentType { Main = "main", Orchestration = "orchestration", Planning = "planning", - Execution = "execution" + Execution = "execution", + QuickAction = "quickAction" } \ No newline at end of file diff --git a/Enums/ApiProvider.ts b/Enums/ApiProvider.ts index 24bb190..47a567c 100644 --- a/Enums/ApiProvider.ts +++ b/Enums/ApiProvider.ts @@ -17,6 +17,10 @@ export function fromModel(model: string): AIProvider { } } +export function isvalidProvider(value: string): value is AIProvider { + return Object.values(AIProvider).includes(value as AIProvider); +} + export function isValidProviderModel(model: string): model is AIProviderModel { return Object.values(AIProviderModel).includes(model as AIProviderModel); } @@ -37,6 +41,19 @@ function isMistralModel(model: string): boolean { return isValidProviderModel(model) && model.startsWith("mistral-"); } +export function modelMatchesProvider(model: AIProviderModel, provider: AIProvider): boolean { + switch (provider) { + case AIProvider.Claude: + return isClaudeModel(model); + case AIProvider.Gemini: + return isGeminiModel(model); + case AIProvider.OpenAI: + return isOpenAIModel(model); + case AIProvider.Mistral: + return isMistralModel(model); + } +} + export enum AIProvider { Claude = "Claude", Gemini = "Gemini", @@ -99,4 +116,18 @@ export enum AIFileServiceURL { export enum MistralAgentEndpoint { Url = "https://api.mistral.ai/v1/agents", ConversationsUrl = "https://api.mistral.ai/v1/conversations" -} \ No newline at end of file +} + +export const DEFAULT_MODEL_BY_PROVIDER: Record = { + [AIProvider.Claude]: AIProviderModel.ClaudeHaiku_4_5, + [AIProvider.Gemini]: AIProviderModel.GeminiFlash_2_5_Lite, + [AIProvider.OpenAI]: AIProviderModel.GPT_5_4_Nano, + [AIProvider.Mistral]: AIProviderModel.MistralSmall, +}; + +export const DEFAULT_PLANNING_MODEL_BY_PROVIDER: Record = { + [AIProvider.Claude]: AIProviderModel.ClaudeSonnet_4_6, + [AIProvider.Gemini]: AIProviderModel.GeminiPro_2_5, + [AIProvider.OpenAI]: AIProviderModel.GPT_5_4_Pro, + [AIProvider.Mistral]: AIProviderModel.MistralLarge, +}; \ No newline at end of file diff --git a/Enums/Copy.ts b/Enums/Copy.ts index 84fcc19..7d36363 100644 --- a/Enums/Copy.ts +++ b/Enums/Copy.ts @@ -62,6 +62,8 @@ export enum Copy { SettingModelDesc = "Select the AI model to use.", SettingPlanningModelDesc = "Select the AI model to use when planning complex tasks.", SettingPlanningModelTip = "Tip: You can reduce cost by using a more powerful model for planning and a cheaper model for the regular agent.", + SettingQuickActionModel = "Quick Actions Model", + SettingQuickActionModelDesc = "Select the AI model to use for quick actions. A fast, lightweight model is recommended.", SettingApiKeyDesc = "Enter your API key here.", SettingFileExclusionsDesc = "Set which directories and files the AI should ignore. Enter one path per line - supports glob patterns like folder/**, *.md", SettingSearchResultsLimitDesc = "Set the maximum number of results provided to the AI when it searches through files in your vault. Higher values provide more context but increase search time.", diff --git a/Helpers/Helpers.ts b/Helpers/Helpers.ts index a27444a..e46f65f 100644 --- a/Helpers/Helpers.ts +++ b/Helpers/Helpers.ts @@ -56,5 +56,5 @@ export function pathExtname(filePath: string) { } export async function sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise(resolve => activeWindow.setTimeout(resolve, ms)); } \ No newline at end of file diff --git a/Helpers/StringTools.ts b/Helpers/StringTools.ts index e242aef..351d15c 100644 --- a/Helpers/StringTools.ts +++ b/Helpers/StringTools.ts @@ -112,7 +112,7 @@ export abstract class StringTools { } } - const canvas = document.createElement("canvas"); + const canvas = activeDocument.createElement("canvas"); canvas.width = width; canvas.height = height; const context = canvas.getContext("2d"); diff --git a/Services/AIServices/AIToolService.ts b/Services/AIServices/AIToolService.ts index e3cba1b..7ad4d02 100644 --- a/Services/AIServices/AIToolService.ts +++ b/Services/AIServices/AIToolService.ts @@ -281,7 +281,7 @@ export class AIToolService { private async readVaultFiles(filePaths: string[]): Promise { const results = await Promise.all( filePaths.map(async (filePath) => { - const result = await this.fileSystemService.readFile(filePath); + const result = await this.fileSystemService.readFilePath(filePath); if (result instanceof Error) { return { path: filePath, error: result.message }; } @@ -324,7 +324,7 @@ export class AIToolService { } private async writeVaultFile(filePath: string, content: string): Promise { - const result = await this.fileSystemService.writeFile(normalizePath(filePath), content); + const result = await this.fileSystemService.writeToFilePath(normalizePath(filePath), content); if (result instanceof Error) { return new AIToolResponsePayload({ success: false, error: result.message }); } @@ -332,7 +332,7 @@ export class AIToolService { } private async patchVaultFile(filePath: string, oldContent: string[], newContent: string[]): Promise { - const result = await this.fileSystemService.patchFile(normalizePath(filePath), oldContent, newContent); + const result = await this.fileSystemService.patchFileAtPath(normalizePath(filePath), oldContent, newContent); if (result instanceof Error) { return new AIToolResponsePayload({ success: false, error: result.message }); } diff --git a/Services/AIServices/QuickAgent.ts b/Services/AIServices/QuickAgent.ts new file mode 100644 index 0000000..4a77ecb --- /dev/null +++ b/Services/AIServices/QuickAgent.ts @@ -0,0 +1,55 @@ +import { AgentType } from "Enums/AgentType"; +import { BaseAgent } from "./BaseAgent"; +import { Conversation } from "Conversations/Conversation"; +import { Exception } from "Helpers/Exception"; +import { AIToolUsageMode } from "Enums/AIToolUsageMode"; +import type { IChatServiceCallbacks } from "Services/ChatService"; +import { ConversationContent } from "Conversations/ConversationContent"; +import { Role } from "Enums/Role"; + +export class QuickAgent extends BaseAgent { + + public async quickAction(action: string, context: string): Promise { + + this.setAgentPromptAndTools(action); + + const conversation = new Conversation(); + const conversationContent = new ConversationContent({ + role: Role.User, + content: context, + }); + conversation.contents.push(conversationContent); + + return await this.requestAgentResponse(AgentType.QuickAction, conversation, this.callbacks()); + } + + private setAgentPromptAndTools(instruction: string): void { + if (!this.ai) { + Exception.throw("Error: No AI provider has been set!"); + } + this.ai.agentType = AgentType.QuickAction; + this.ai.aiToolUsageMode = AIToolUsageMode.Disabled; + this.ai.systemPrompt = instruction; + this.ai.userInstruction = ""; // do not include user instruction for quick agent + this.ai.aiToolDefinitions = []; // no tools for quick agent + } + + private callbacks(): IChatServiceCallbacks { + return { + onSubmit: () => {}, + onStreamingUpdate: () => {}, + onThoughtUpdate: () => {}, + onToolCallStarted: () => {}, + onPlanningStarted: () => {}, + onPlanningFinished: () => {}, + onUserQuestion: async () => { + return new Promise(() => {}); + }, + onPlanUpdate: () => {}, + onPlanStepUpdate: () => {}, + onPlanReset: () => {}, + onComplete: () => {}, + }; + } + +} \ No newline at end of file diff --git a/Services/ChatService.ts b/Services/ChatService.ts index 5e028e1..4b69879 100644 --- a/Services/ChatService.ts +++ b/Services/ChatService.ts @@ -112,7 +112,7 @@ export class ChatService { await this.mainAgent.runMainAgent(conversation, chatMode, callbacks); if (namingPromise) { - const timeout = new Promise(resolve => setTimeout(resolve, 5000)); + const timeout = new Promise(resolve => activeWindow.setTimeout(resolve, 5000)); await Promise.race([namingPromise, timeout]); } }); diff --git a/Services/FileSystemService.ts b/Services/FileSystemService.ts index 6f1bd5d..d219844 100644 --- a/Services/FileSystemService.ts +++ b/Services/FileSystemService.ts @@ -17,7 +17,11 @@ export class FileSystemService { return await this.vaultService.exists(filePath, allowAccessToPluginRoot); } - public async readFile(filePath: string, allowAccessToPluginRoot: boolean = false): Promise { + public async readFile(file: TFile, allowAccessToPluginRoot: boolean = false): Promise { + return await this.vaultService.read(file, allowAccessToPluginRoot); + } + + public async readFilePath(filePath: string, allowAccessToPluginRoot: boolean = false): Promise { const file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath, allowAccessToPluginRoot); if (file == null) { return Exception.new(`File does not exist: ${filePath}`); @@ -43,7 +47,11 @@ export class FileSystemService { return Exception.new(`Path is a folder, not a file: ${filePath}`); } - public async writeFile(filePath: string, content: string, allowAccessToPluginRoot: boolean = false, requiresConfirmation: boolean = true): Promise { + public async writeToFile(file: TFile, content: string, allowAccessToPluginRoot: boolean = false, requiresConfirmation: boolean = true): Promise { + return await this.vaultService.modify(file, content, allowAccessToPluginRoot, requiresConfirmation); + } + + public async writeToFilePath(filePath: string, content: string, allowAccessToPluginRoot: boolean = false, requiresConfirmation: boolean = true): Promise { const file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath, allowAccessToPluginRoot); if (file == null || !(file instanceof TFile)) { return await this.vaultService.create(filePath, content, allowAccessToPluginRoot, requiresConfirmation); @@ -59,7 +67,11 @@ export class FileSystemService { return await this.vaultService.modifyBinary(file, data, allowAccessToPluginRoot); } - public async patchFile(filePath: string, oldContent: string[], newContent: string[], allowAccessToPluginRoot: boolean = false, requiresConfirmation: boolean = true): Promise { + public async patchFile(file: TFile, oldContent: string[], newContent: string[], allowAccessToPluginRoot: boolean = false, requiresConfirmation: boolean = true): Promise { + return await this.vaultService.patch(file, oldContent, newContent, allowAccessToPluginRoot, requiresConfirmation); + } + + public async patchFileAtPath(filePath: string, oldContent: string[], newContent: string[], allowAccessToPluginRoot: boolean = false, requiresConfirmation: boolean = true): Promise { const file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath, allowAccessToPluginRoot); let fileToPatch: TFile; @@ -67,7 +79,7 @@ export class FileSystemService { fileToPatch = file; } else { // if the file doesn't exist we may as well create it even though this is just a patch operation - const result = await this.writeFile(filePath, "", allowAccessToPluginRoot, requiresConfirmation); + const result = await this.writeToFilePath(filePath, "", allowAccessToPluginRoot, requiresConfirmation); if (result instanceof Error) { return result; } diff --git a/Services/HTMLService.ts b/Services/HTMLService.ts index 658c7ff..06c4c66 100644 --- a/Services/HTMLService.ts +++ b/Services/HTMLService.ts @@ -12,7 +12,7 @@ export class HTMLService { public parseHTMLString(htmlString: string): DocumentFragment { const parser = new DOMParser(); - const fragment = document.createDocumentFragment(); + const fragment = activeDocument.createDocumentFragment(); const doc = parser.parseFromString(htmlString, "text/html"); // Transfer all nodes from the parsed body to the fragment @@ -26,7 +26,7 @@ export class HTMLService { // Creates a temporary container, parses HTML, and returns the container. // Useful for parsing HTML when you need to traverse the resulting DOM structure. public parseHTMLToContainer(htmlString: string): HTMLDivElement { - const container = document.createElement("div"); + const container = activeDocument.createElement("div"); const fragment = this.parseHTMLString(htmlString); container.appendChild(fragment); return container; diff --git a/Services/InputService.ts b/Services/InputService.ts index 3b1f402..6294849 100644 --- a/Services/InputService.ts +++ b/Services/InputService.ts @@ -166,7 +166,7 @@ export class InputService { } public getCursorPosition(element: HTMLElement): number { - const selection = window.getSelection() || new Selection(); + const selection = activeWindow.window.getSelection() || new Selection(); if (selection.rangeCount === 0) { return -1; @@ -201,8 +201,8 @@ export class InputService { try { // Create range and selection - const range = document.createRange(); - const selection = window.getSelection() ?? new Selection(); + const range = activeWindow.document.createRange(); + const selection = activeWindow.getSelection() ?? new Selection(); // Find the text node and position const result = this.findTextNodeAndOffset(element, targetPosition); @@ -236,7 +236,7 @@ export class InputService { return; } - const selection = window.getSelection(); + const selection = activeWindow.getSelection(); if (!selection || selection.rangeCount === 0) { return; } @@ -244,7 +244,7 @@ export class InputService { const range = selection.getRangeAt(0); range.deleteContents(); - const textNode = document.createTextNode(text); + const textNode = activeDocument.createTextNode(text); range.insertNode(textNode); range.setStartAfter(textNode); @@ -259,7 +259,7 @@ export class InputService { return; } - const selection = window.getSelection(); + const selection = activeWindow.getSelection(); if (!selection || selection.rangeCount === 0) { return; } @@ -283,13 +283,13 @@ export class InputService { return; } - const selection = window.getSelection(); + const selection = activeWindow.getSelection(); if (!selection) { return; } try { - const range = document.createRange(); + const range = activeDocument.createRange(); // Find the text nodes and offsets for start and end positions const startResult = this.findTextNodeAndOffset(element, startPos); @@ -323,7 +323,7 @@ export class InputService { * If it is, repositions the cursor to a valid location. */ private ensureCursorNotInNonEditableElement(element: HTMLElement) { - const selection = window.getSelection(); + const selection = activeWindow.getSelection(); if (!selection || selection.rangeCount === 0) { return; } @@ -349,13 +349,13 @@ export class InputService { * Positions the cursor immediately after the given element. */ private positionCursorAfterElement(targetElement: HTMLElement, container: HTMLElement) { - const selection = window.getSelection(); + const selection = activeWindow.getSelection(); if (!selection) { return; } try { - const range = document.createRange(); + const range = activeDocument.createRange(); // Try to position cursor in the next text node or after the element const nextSibling = targetElement.nextSibling; diff --git a/Services/MemoriesService.ts b/Services/MemoriesService.ts index b960bd0..d161555 100644 --- a/Services/MemoriesService.ts +++ b/Services/MemoriesService.ts @@ -26,7 +26,7 @@ export class MemoriesService { } public async readMemories(): Promise { - const result = await this.fileSystemService.readFile(Path.Memories, true); + const result = await this.fileSystemService.readFilePath(Path.Memories, true); if (result instanceof Error) { return Copy.MemoriesEmpty; @@ -41,7 +41,7 @@ export class MemoriesService { [this.maxMemoriesLength.toString(), this.maxMemoriesLineLength.toString()]); } - const result = await this.fileSystemService.writeFile(Path.Memories, newMemories, true, false); + const result = await this.fileSystemService.writeToFilePath(Path.Memories, newMemories, true, false); return result instanceof Error ? result : Copy.MemoriesUpdatedSuccess; } diff --git a/Services/QuickActionsService.ts b/Services/QuickActionsService.ts new file mode 100644 index 0000000..7b649af --- /dev/null +++ b/Services/QuickActionsService.ts @@ -0,0 +1,84 @@ +import { Resolve } from "./DependencyService"; +import { Services } from "./Services"; +import { AbortService } from "./AbortService"; +import type { QuickAgent } from "./AIServices/QuickAgent"; +import type VaultkeeperAIPlugin from "main"; +import type { Editor, MarkdownFileInfo, MarkdownView, Menu } from "obsidian"; +import type { FileSystemService } from "./FileSystemService"; +import { BeautifyPrompt } from "AIPrompts/QuickActionPrompts/Beautify"; + +export class QuickActionsService { + + private plugin: VaultkeeperAIPlugin; + private abortService: AbortService; + private fileSystemService: FileSystemService; + + public constructor() { + this.plugin = Resolve(Services.VaultkeeperAIPlugin); + this.abortService = Resolve(Services.AbortService); + this.fileSystemService = Resolve(Services.FileSystemService); + + this.registerEditorMenuActions(); + } + + /* Edit Menu Action Definitions */ + + private async beautify(menu: Menu, editor: Editor, view: MarkdownView | MarkdownFileInfo) { + const file = view.file; + if (!file) { + return; + } + + const selection = editor.getSelection(); + const content = await this.fileSystemService.readFile(file); + + if (content instanceof Error) { + return; // Likely an excluded file + } + + if (selection.length > 0) { + const result = await this.newAction(BeautifyPrompt, selection); + await this.fileSystemService.patchFile(file, [selection], [result], false, false); + } else { + const result = await this.newAction(BeautifyPrompt, content); + await this.fileSystemService.writeToFile(file, result, false, false); + } + } + + private async applyTemplate(menu: Menu, editor: Editor, view: MarkdownView | MarkdownFileInfo) { + } + + private async newAction(action: string, context: string): Promise { + return this.abortService.abortableOperation(async () => { + const agent = Resolve(Services.QuickAgent); + agent.resolveAIProvider(); + return agent.quickAction(action, context); + }); + } + + /* Registered Edit Menu Actions */ + private registerEditorMenuActions() { + // Beautify + this.plugin.registerEvent( + this.plugin.app.workspace.on("editor-menu", (menu, editor, view) => { + menu.addItem((item) => { + item.setTitle("Beautify") + .setIcon("palette") + .onClick(async () => this.beautify(menu, editor, view)); + }); + }) + ); + + // Apply Template + this.plugin.registerEvent( + this.plugin.app.workspace.on("editor-menu", (menu, editor, view) => { + menu.addItem((item) => { + item.setTitle("Apply template") + .setIcon("notepad-text-dashed") + .onClick(async () => this.applyTemplate(menu, editor, view)); + }); + }) + ); + } + +} \ No newline at end of file diff --git a/Services/ServiceRegistration.ts b/Services/ServiceRegistration.ts index 4c8f79c..089da2d 100644 --- a/Services/ServiceRegistration.ts +++ b/Services/ServiceRegistration.ts @@ -56,6 +56,8 @@ import { OpenAIFileService } from "AIClasses/OpenAI/OpenAIFileService"; // Prompts import { AIPrompt, type IPrompt } from "AIPrompts/IPrompt"; +import { QuickAgent } from "./AIServices/QuickAgent"; +import { QuickActionsService } from "./QuickActionsService"; export async function RegisterPlugin(plugin: VaultkeeperAIPlugin) { RegisterSingleton(Services.VaultkeeperAIPlugin, plugin); @@ -82,6 +84,7 @@ export function RegisterDependencies() { RegisterSingleton(Services.MemoriesService, new MemoriesService()); RegisterSingleton(Services.ConversationFileSystemService, new ConversationFileSystemService()); RegisterSingleton(Services.ConversationNamingService, new ConversationNamingService()); + RegisterSingleton(Services.QuickActionsService, new QuickActionsService()); RegisterTransient(Services.WebViewerService, () => new WebViewerService()); @@ -91,6 +94,7 @@ export function RegisterDependencies() { RegisterSingleton(Services.StreamingService, new StreamingService()); RegisterSingleton(Services.ChatService, new ChatService()); + RegisterTransient(Services.QuickAgent, () => new QuickAgent()); RegisterTransient(Services.StreamingMarkdownService, () => new StreamingMarkdownService()); RegisterTransient(Services.InputService, () => new InputService()); diff --git a/Services/Services.ts b/Services/Services.ts index 672183a..31503dc 100644 --- a/Services/Services.ts +++ b/Services/Services.ts @@ -11,11 +11,13 @@ export class Services { static FileSystemService = Symbol("FileSystemService"); static ConversationFileSystemService = Symbol("ConversationFileSystemService"); static ConversationNamingService = Symbol("ConversationNamingService"); + static QuickActionsService = Symbol("QuickActionsService"); static StreamingService = Symbol("StreamingService"); static MarkdownService = Symbol("MarkdownService"); static StreamingMarkdownService = Symbol("StreamingMarkdownService"); static AIToolService = Symbol("AIToolService"); static MainAgent = Symbol("MainAgent"); + static QuickAgent = Symbol("QuickAgent"); static ChatService = Symbol("ChatService"); static SanitiserService = Symbol("SanitiserService"); static InputService = Symbol("InputService"); diff --git a/Services/SettingsService.ts b/Services/SettingsService.ts index 38ae1ce..3f8359f 100644 --- a/Services/SettingsService.ts +++ b/Services/SettingsService.ts @@ -1,14 +1,17 @@ import type VaultkeeperAIPlugin from "main"; import { Resolve } from "./DependencyService"; import { Services } from "./Services"; -import { AIProvider, AIProviderModel, fromModel, isValidProviderModel } from "Enums/ApiProvider"; +import { AIProvider, AIProviderModel, DEFAULT_MODEL_BY_PROVIDER, DEFAULT_PLANNING_MODEL_BY_PROVIDER, fromModel, isvalidProvider, isValidProviderModel, modelMatchesProvider } from "Enums/ApiProvider"; const DEFAULT_SETTINGS: IVaultkeeperAISettings = { firstTimeStart: true, userInstruction: "", + provider: AIProvider.Claude, model: AIProviderModel.ClaudeHaiku_4_5, planningModel: AIProviderModel.ClaudeSonnet_4_6, + quickActionModel: AIProviderModel.ClaudeHaiku_4_5, + apiKeys: { claude: "", openai: "", @@ -31,8 +34,11 @@ export interface IVaultkeeperAISettings { firstTimeStart: boolean; userInstruction: string; - model: string; - planningModel: string; + provider: AIProvider; + model: AIProviderModel; + planningModel: AIProviderModel; + quickActionModel: AIProviderModel; + apiKeys: { claude: string; openai: string; @@ -106,12 +112,31 @@ export class SettingsService { } private ensureValidModels(): void { - const validModel = isValidProviderModel(this.settings.model); - const validPlanningModel = isValidProviderModel(this.settings.model); + let changed = false; - if (!validModel || !validPlanningModel) { - this.settings.model = AIProviderModel.ClaudeSonnet_4_6; - this.settings.planningModel = AIProviderModel.ClaudeSonnet_4_6; + let provider = this.settings.provider; + + if (!isvalidProvider(provider)) { + provider = DEFAULT_SETTINGS.provider; + changed = true; + } + + if (!isValidProviderModel(this.settings.model) || !modelMatchesProvider(this.settings.model, provider)) { + this.settings.model = DEFAULT_MODEL_BY_PROVIDER[provider]; + changed = true; + } + + if (!isValidProviderModel(this.settings.planningModel) || !modelMatchesProvider(this.settings.planningModel, provider)) { + this.settings.planningModel = DEFAULT_PLANNING_MODEL_BY_PROVIDER[provider]; + changed = true; + } + + if (!isValidProviderModel(this.settings.quickActionModel) || !modelMatchesProvider(this.settings.quickActionModel, provider)) { + this.settings.quickActionModel = DEFAULT_MODEL_BY_PROVIDER[provider]; + changed = true; + } + + if (changed) { void this.saveSettings(); } } diff --git a/Services/StreamingMarkdownService.ts b/Services/StreamingMarkdownService.ts index f22ad05..8693428 100644 --- a/Services/StreamingMarkdownService.ts +++ b/Services/StreamingMarkdownService.ts @@ -99,12 +99,12 @@ export class StreamingMarkdownService { this.debouncedRender(messageId); } - private renderTimeouts = new Map(); + private renderTimeouts = new Map>(); private debouncedRender(messageId: string, immediate: boolean = false) { const existingTimeout = this.renderTimeouts.get(messageId); if (existingTimeout) { - clearTimeout(existingTimeout); + activeWindow.clearTimeout(existingTimeout); } const render = () => { @@ -127,7 +127,7 @@ export class StreamingMarkdownService { if (immediate) { render(); } else { - const timeout = setTimeout(render, 50); // 50ms debounce + const timeout = activeWindow.setTimeout(render, 50); // 50ms debounce this.renderTimeouts.set(messageId, timeout); } } @@ -148,7 +148,7 @@ export class StreamingMarkdownService { this.streamingStates.delete(messageId); const timeout = this.renderTimeouts.get(messageId); if (timeout) { - clearTimeout(timeout); + activeWindow.clearTimeout(timeout); this.renderTimeouts.delete(messageId); } } diff --git a/Services/WebViewerService.ts b/Services/WebViewerService.ts index d1cb082..a3c6aef 100644 --- a/Services/WebViewerService.ts +++ b/Services/WebViewerService.ts @@ -72,7 +72,7 @@ export class WebViewerService { if (Date.now() - start > timeoutMs) { return false; } - await new Promise(r => setTimeout(r, 200)); + await new Promise(r => activeWindow.setTimeout(r, 200)); } return true; } diff --git a/Types/ApiError.ts b/Types/ApiError.ts index bdc14df..2fa0bd5 100644 --- a/Types/ApiError.ts +++ b/Types/ApiError.ts @@ -34,7 +34,7 @@ export class ApiError extends Error { let isRetryable: boolean; // Parse response body for provider-specific messages - let providerMessage = ""; + let providerMessage: string; try { const parsed = JSON.parse(responseBody) as { error?: { message?: string }; message?: string }; providerMessage = parsed.error?.message || parsed.message || ""; diff --git a/Views/VaultkeeperAISettingTab.ts b/Views/VaultkeeperAISettingTab.ts index 353ba4e..61e7452 100644 --- a/Views/VaultkeeperAISettingTab.ts +++ b/Views/VaultkeeperAISettingTab.ts @@ -1,4 +1,4 @@ -import { AIProvider, AIProviderModel, fromModel } from "Enums/ApiProvider"; +import { AIProvider, AIProviderModel, fromModel, isValidProviderModel } from "Enums/ApiProvider"; import { Copy } from "Enums/Copy"; import { Selector } from "Enums/Selector"; import type VaultkeeperAIPlugin from "main"; @@ -20,6 +20,7 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { private apiKeyInputEl: HTMLInputElement | null = null; private fileDisclaimerSetting: Setting | null = null; private planningModelDropdown: DropdownComponent | null = null; + private quickActionModelDropdown: DropdownComponent | null = null; private allowUpdatingMemoriesSetting: Setting | null = null; private allowUpdatingMemoriesToggleComponent: ToggleComponent | null = null; @@ -46,34 +47,24 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { this.populateModelDropdown(dropdown); dropdown.setValue(this.settingsService.settings.model); dropdown.onChange(async (value) => { + if (!isValidProviderModel(value)) { + return; + } this.settingsService.settings.model = value; + this.settingsService.settings.provider = fromModel(value); await this.settingsService.saveSettings(() => RegisterAiProvider()); if (this.apiKeyInputEl) { this.apiKeyInputEl.value = this.settingsService.getApiKeyForCurrentModel(); this.highlightApiKey(); } this.updateFileDisclaimer(); - await this.updatePlanningModelDropdown(); + await this.updateModelDropdowns(); }); }); - /* Model files API disclaimer */ - this.fileDisclaimerSetting = new Setting(containerEl) - .setDesc(Copy.SettingFileMonitoringClaude) - .addExtraButton(button => { - button - .setTooltip(Copy.TooltipLearnMoreFileMonitoring) - .onClick(() => { - const modal = Resolve(Services.HelpModal); - modal.open(2); // Opens HelpModal to "Plugin Guide" (topic 2) - }); - setIcon(button.extraSettingsEl, "help-circle"); - }); - this.updateFileDisclaimer(); - /* Planning Model Selection Setting */ const currentProvider = fromModel(this.settingsService.settings.model); - const planningModelDescFragment = document.createDocumentFragment(); + const planningModelDescFragment = activeDocument.createDocumentFragment(); planningModelDescFragment.appendText(Copy.SettingPlanningModelDesc); planningModelDescFragment.createEl("br"); planningModelDescFragment.createEl("br"); @@ -86,11 +77,31 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { this.populateModelDropdown(dropdown, currentProvider); dropdown.setValue(this.settingsService.settings.planningModel); dropdown.onChange(async (value) => { + if (!isValidProviderModel(value)) { + return; + } this.settingsService.settings.planningModel = value; await this.settingsService.saveSettings(); }); }); + /* Quick Action Model Selection Setting */ + new Setting(containerEl) + .setName(Copy.SettingQuickActionModel) + .setDesc(Copy.SettingQuickActionModelDesc) + .addDropdown((dropdown) => { + this.quickActionModelDropdown = dropdown; + this.populateModelDropdown(dropdown); + dropdown.setValue(this.settingsService.settings.quickActionModel); + dropdown.onChange(async (value) => { + if (!isValidProviderModel(value)) { + return; + } + this.settingsService.settings.quickActionModel = value; + await this.settingsService.saveSettings(); + }); + }); + /* API Key Setting */ this.apiKeySetting = new Setting(containerEl) .setName(Copy.SettingApiKey) @@ -125,6 +136,20 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { }); this.highlightApiKey(); + /* Model files API disclaimer */ + this.fileDisclaimerSetting = new Setting(containerEl) + .setDesc(Copy.SettingFileMonitoringClaude) + .addExtraButton(button => { + button + .setTooltip(Copy.TooltipLearnMoreFileMonitoring) + .onClick(() => { + const modal = Resolve(Services.HelpModal); + modal.open(2); // Opens HelpModal to "Plugin Guide" (topic 2) + }); + setIcon(button.extraSettingsEl, "help-circle"); + }); + this.updateFileDisclaimer(); + /* Exclusions Setting */ new Setting(containerEl) .setName(Copy.SettingFileExclusions) @@ -286,23 +311,39 @@ export class VaultkeeperAISettingTab extends PluginSettingTab { } } - private async updatePlanningModelDropdown(): Promise { - if (!this.planningModelDropdown) return; - + private async updateModelDropdowns(): Promise { const currentProvider = fromModel(this.settingsService.settings.model); - const planningProvider = fromModel(this.settingsService.settings.planningModel); + let shouldSave = false; - // Clear existing options - this.planningModelDropdown.selectEl.empty(); - this.populateModelDropdown(this.planningModelDropdown, currentProvider); + if (this.planningModelDropdown) { + const planningProvider = fromModel(this.settingsService.settings.planningModel); + this.planningModelDropdown.selectEl.empty(); + this.populateModelDropdown(this.planningModelDropdown, currentProvider); - // If planning model provider doesn't match, reset to main model - if (planningProvider !== currentProvider) { - this.settingsService.settings.planningModel = this.settingsService.settings.model; - await this.settingsService.saveSettings(); + if (planningProvider !== currentProvider) { + this.settingsService.settings.planningModel = this.settingsService.settings.model; + shouldSave = true; + } + + this.planningModelDropdown.setValue(this.settingsService.settings.planningModel); } - this.planningModelDropdown.setValue(this.settingsService.settings.planningModel); + if (this.quickActionModelDropdown) { + const quickActionProvider = fromModel(this.settingsService.settings.quickActionModel); + this.quickActionModelDropdown.selectEl.empty(); + this.populateModelDropdown(this.quickActionModelDropdown); + + if (quickActionProvider !== currentProvider) { + this.settingsService.settings.quickActionModel = this.settingsService.settings.model; + shouldSave = true; + } + + this.quickActionModelDropdown.setValue(this.settingsService.settings.quickActionModel); + } + + if (shouldSave) { + await this.settingsService.saveSettings(); + } } private highlightApiKey() { diff --git a/__tests__/Services/FileSystemService.test.ts b/__tests__/Services/FileSystemService.test.ts index b74d524..5fcc876 100644 --- a/__tests__/Services/FileSystemService.test.ts +++ b/__tests__/Services/FileSystemService.test.ts @@ -83,7 +83,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.read = vi.fn().mockResolvedValue(fileContent); - const result = await fileSystemService.readFile('test.md'); + const result = await fileSystemService.readFilePath('test.md'); expect(result).toBe(fileContent); expect(mockVaultService.getAbstractFileByPath).toHaveBeenCalledWith('test.md', false); @@ -93,7 +93,7 @@ describe('FileSystemService', () => { it('should return Error when file does not exist', async () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(null); - const result = await fileSystemService.readFile('nonexistent.md'); + const result = await fileSystemService.readFilePath('nonexistent.md'); expect(result).toBeInstanceOf(Error); expect((result as Error).message).toContain('File does not exist: '); @@ -107,7 +107,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.read = vi.fn().mockResolvedValue(fileContent); - await fileSystemService.readFile('plugin/config.json', true); + await fileSystemService.readFilePath('plugin/config.json', true); expect(mockVaultService.getAbstractFileByPath).toHaveBeenCalledWith('plugin/config.json', true); expect(mockVaultService.read).toHaveBeenCalledWith(mockFile, true); @@ -118,7 +118,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFolder); - const result = await fileSystemService.readFile('folder'); + const result = await fileSystemService.readFilePath('folder'); expect(result).toBeInstanceOf(Error); expect((result as Error).message).toContain('Path is a folder, not a file'); @@ -132,7 +132,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(null); mockVaultService.create = vi.fn().mockResolvedValue(mockFile); - const result = await fileSystemService.writeFile('new.md', 'content'); + const result = await fileSystemService.writeToFilePath('new.md', 'content'); expect(result).toBe(mockFile); expect(mockVaultService.create).toHaveBeenCalledWith('new.md', 'content', false, true); @@ -145,7 +145,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.modify = vi.fn().mockResolvedValue(mockFile); - const result = await fileSystemService.writeFile('existing.md', 'new content'); + const result = await fileSystemService.writeToFilePath('existing.md', 'new content'); expect(result).toBe(mockFile); expect(mockVaultService.modify).toHaveBeenCalledWith(mockFile, 'new content', false, true); @@ -156,7 +156,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(null); mockVaultService.create = vi.fn().mockResolvedValue(undefined); - await fileSystemService.writeFile('plugin/data.json', 'content', true); + await fileSystemService.writeToFilePath('plugin/data.json', 'content', true); expect(mockVaultService.getAbstractFileByPath).toHaveBeenCalledWith('plugin/data.json', true); expect(mockVaultService.create).toHaveBeenCalledWith('plugin/data.json', 'content', true, true); @@ -168,7 +168,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(null); mockVaultService.create = vi.fn().mockResolvedValue(error); - const result = await fileSystemService.writeFile('error.md', 'content'); + const result = await fileSystemService.writeToFilePath('error.md', 'content'); expect(result).toBeInstanceOf(Error); expect((result as Error).message).toBe('Create failed'); @@ -181,7 +181,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.modify = vi.fn().mockResolvedValue(error); - const result = await fileSystemService.writeFile('existing.md', 'content'); + const result = await fileSystemService.writeToFilePath('existing.md', 'content'); expect(result).toBeInstanceOf(Error); expect((result as Error).message).toBe('Modify failed'); @@ -197,7 +197,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.patch = vi.fn().mockResolvedValue(mockFile); - const result = await fileSystemService.patchFile('existing.md', oldContent, newContent); + const result = await fileSystemService.patchFileAtPath('existing.md', oldContent, newContent); expect(result).toBe(mockFile); expect(mockVaultService.patch).toHaveBeenCalledWith(mockFile, oldContent, newContent, false, true); @@ -215,7 +215,7 @@ describe('FileSystemService', () => { mockVaultService.create = vi.fn().mockResolvedValue(mockFile); mockVaultService.patch = vi.fn().mockResolvedValue(mockFile); - const result = await fileSystemService.patchFile('new.md', oldContent, newContent); + const result = await fileSystemService.patchFileAtPath('new.md', oldContent, newContent); // writeFile should create the file with empty content expect(mockVaultService.create).toHaveBeenCalledWith('new.md', '', false, true); @@ -232,7 +232,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.patch = vi.fn().mockResolvedValue(error); - const result = await fileSystemService.patchFile('existing.md', oldContent, newContent); + const result = await fileSystemService.patchFileAtPath('existing.md', oldContent, newContent); expect(result).toBeInstanceOf(Error); expect((result as Error).message).toContain('Content to replace was not found in the file'); @@ -246,7 +246,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(null); mockVaultService.create = vi.fn().mockResolvedValue(error); - const result = await fileSystemService.patchFile('new.md', oldContent, newContent); + const result = await fileSystemService.patchFileAtPath('new.md', oldContent, newContent); expect(result).toBeInstanceOf(Error); expect((result as Error).message).toBe('Create failed'); @@ -261,7 +261,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.patch = vi.fn().mockResolvedValue(mockFile); - await fileSystemService.patchFile('plugin/config.md', oldContent, newContent, true); + await fileSystemService.patchFileAtPath('plugin/config.md', oldContent, newContent, true); expect(mockVaultService.getAbstractFileByPath).toHaveBeenCalledWith('plugin/config.md', true); expect(mockVaultService.patch).toHaveBeenCalledWith(mockFile, oldContent, newContent, true, true); @@ -275,7 +275,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.patch = vi.fn().mockResolvedValue(mockFile); - const result = await fileSystemService.patchFile('document.md', oldContent, newContent); + const result = await fileSystemService.patchFileAtPath('document.md', oldContent, newContent); expect(result).toBe(mockFile); expect(mockVaultService.patch).toHaveBeenCalledWith(mockFile, oldContent, newContent, false, true); @@ -289,7 +289,7 @@ describe('FileSystemService', () => { mockVaultService.create = vi.fn().mockResolvedValue(createMockFile('new.md')); mockVaultService.patch = vi.fn().mockResolvedValue(createMockFile('new.md')); - await fileSystemService.patchFile('new.md', oldContent, newContent); + await fileSystemService.patchFileAtPath('new.md', oldContent, newContent); // Should call patch on the created file expect(mockVaultService.create).toHaveBeenCalledWith('new.md', '', false, true); @@ -304,7 +304,7 @@ describe('FileSystemService', () => { mockVaultService.getAbstractFileByPath = vi.fn().mockReturnValue(mockFile); mockVaultService.patch = vi.fn().mockResolvedValue(mockFile); - await fileSystemService.patchFile('test.md', oldContent, newContent, false, true); + await fileSystemService.patchFileAtPath('test.md', oldContent, newContent, false, true); expect(mockVaultService.patch).toHaveBeenCalledWith(mockFile, oldContent, newContent, false, true); }); diff --git a/__tests__/Services/SettingsService.test.ts b/__tests__/Services/SettingsService.test.ts index 80f34f4..ddca9a9 100644 --- a/__tests__/Services/SettingsService.test.ts +++ b/__tests__/Services/SettingsService.test.ts @@ -103,7 +103,9 @@ describe('SettingsService', () => { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; settingsService = new SettingsService(loadedSettings); }); @@ -148,7 +150,9 @@ describe('SettingsService', () => { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; settingsService = new SettingsService(loadedSettings); @@ -173,7 +177,9 @@ describe('SettingsService', () => { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; settingsService = new SettingsService(loadedSettings); @@ -198,7 +204,9 @@ describe('SettingsService', () => { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; settingsService = new SettingsService(loadedSettings); @@ -248,7 +256,9 @@ describe('SettingsService', () => { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; settingsService = new SettingsService(loadedSettings); }); @@ -307,7 +317,9 @@ describe('SettingsService', () => { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; settingsService = new SettingsService(loadedSettings); }); diff --git a/__tests__/Services/VaultCacheService.performance.test.ts b/__tests__/Services/VaultCacheService.performance.test.ts index 6fc1e05..44d048e 100644 --- a/__tests__/Services/VaultCacheService.performance.test.ts +++ b/__tests__/Services/VaultCacheService.performance.test.ts @@ -6,7 +6,7 @@ import { SettingsService, type IVaultkeeperAISettings } from '../../Services/Set import { SanitiserService } from '../../Services/SanitiserService'; import { RegisterSingleton, DeregisterAllServices } from '../../Services/DependencyService'; import { Services } from '../../Services/Services'; -import { AIProviderModel } from '../../Enums/ApiProvider'; +import { AIProvider, AIProviderModel } from '../../Enums/ApiProvider'; import type VaultkeeperAIPlugin from '../../main'; // Mock getAllTags from obsidian @@ -103,7 +103,9 @@ const mockSettings: IVaultkeeperAISettings = { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; let settingsService: SettingsService; diff --git a/__tests__/Services/VaultService.pdf.test.ts b/__tests__/Services/VaultService.pdf.test.ts index e16196d..b22be2c 100644 --- a/__tests__/Services/VaultService.pdf.test.ts +++ b/__tests__/Services/VaultService.pdf.test.ts @@ -5,7 +5,7 @@ import { RegisterSingleton, DeregisterAllServices } from '../../Services/Depende import { Services } from '../../Services/Services'; import { SanitiserService } from '../../Services/SanitiserService'; import { SettingsService, type IVaultkeeperAISettings } from '../../Services/SettingsService'; -import { AIProviderModel } from '../../Enums/ApiProvider'; +import { AIProvider, AIProviderModel } from '../../Enums/ApiProvider'; import { Exception } from '../../Helpers/Exception'; import * as PDFHelper from '../../Helpers/DocumentHelper'; import type { IPageText } from '../../Types/SearchTypes'; @@ -63,7 +63,9 @@ const mockSettings: IVaultkeeperAISettings = { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; const mockPlugin = { diff --git a/__tests__/Services/VaultService.performance.test.ts b/__tests__/Services/VaultService.performance.test.ts index 8fa24ee..89b5033 100644 --- a/__tests__/Services/VaultService.performance.test.ts +++ b/__tests__/Services/VaultService.performance.test.ts @@ -5,7 +5,7 @@ import { SettingsService, type IVaultkeeperAISettings } from '../../Services/Set import { SanitiserService } from '../../Services/SanitiserService'; import { RegisterSingleton, DeregisterAllServices } from '../../Services/DependencyService'; import { Services } from '../../Services/Services'; -import { AIProviderModel } from '../../Enums/ApiProvider'; +import { AIProvider, AIProviderModel } from '../../Enums/ApiProvider'; import type VaultkeeperAIPlugin from '../../main'; /** @@ -65,7 +65,9 @@ const mockSettings: IVaultkeeperAISettings = { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; let settingsService: SettingsService; diff --git a/__tests__/Services/VaultService.test.ts b/__tests__/Services/VaultService.test.ts index 2f68aec..c339f2e 100644 --- a/__tests__/Services/VaultService.test.ts +++ b/__tests__/Services/VaultService.test.ts @@ -6,7 +6,7 @@ import { RegisterSingleton, DeregisterAllServices } from '../../Services/Depende import { Services } from '../../Services/Services'; import { SanitiserService } from '../../Services/SanitiserService'; import { SettingsService, type IVaultkeeperAISettings } from '../../Services/SettingsService'; -import { AIProviderModel } from '../../Enums/ApiProvider'; +import { AIProvider, AIProviderModel } from '../../Enums/ApiProvider'; import { Exception } from '../../Helpers/Exception'; /** @@ -62,7 +62,9 @@ const mockSettings: IVaultkeeperAISettings = { enableMemories: false, allowUpdatingMemories: true, enableWebSearch: true, - enableWebViewer: false + enableWebViewer: false, + provider: AIProvider.Claude, + quickActionModel: AIProviderModel.ClaudeSonnet_4_6 }; const mockPlugin = { diff --git a/eslint.config.js b/eslint.config.js index 7118f18..6e5813d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,61 +1,51 @@ // eslint.config.js +import { defineConfig } from "eslint/config"; import js from "@eslint/js"; import tseslint from "typescript-eslint"; import obsidianmd from "eslint-plugin-obsidianmd"; -import eslintComments from "eslint-plugin-eslint-comments"; +import eslintComments from "@eslint-community/eslint-plugin-eslint-comments"; +import globals from "globals"; -export default [ - // Ignore patterns +export default defineConfig([ { - ignores: ["node_modules/**", "main.js", "__tests__/**", "*.test.ts", "esbuild.config.mjs", "version-bump.mjs", "vitest.config.ts"] + ignores: [ + "node_modules/**", + "main.js", + "eslint.config.js", + "**/__tests__/**", + "**/*.test.ts", + "esbuild.config.mjs", + "version-bump.mjs", + "vitest.config.ts", + ], }, - // Base ESLint recommended rules js.configs.recommended, - // TypeScript recommended rules (type-checked rules disabled for non-TS files) - ...tseslint.configs.recommendedTypeChecked.map(config => ({ - ...config, - files: ["**/*.ts"], - })), - - // Project-specific configuration { files: ["**/*.ts"], + extends: [ + tseslint.configs.recommendedTypeChecked, + obsidianmd.configs.recommended, + ], plugins: { - obsidianmd: obsidianmd, - "eslint-comments": eslintComments, + "@eslint-community/eslint-comments": eslintComments, }, languageOptions: { parser: tseslint.parser, parserOptions: { - project: true, - sourceType: "module" + projectService: true, + sourceType: "module", }, globals: { - console: "readonly", - AsyncGenerator: "readonly", - require: "readonly", - process: "readonly", + ...globals.browser, + ...globals.node, createEl: "readonly", - join: "readonly", - __dirname: "readonly", - document: "readonly", - window: "readonly", - performance: "readonly", - requestAnimationFrame: "readonly", - cancelAnimationFrame: "readonly", - setTimeout: "readonly", - clearTimeout: "readonly", - NodeJS: "readonly", Fuzzysort: "readonly", - } + AsyncGenerator: "readonly", + }, }, rules: { - // Obsidian plugin recommended rules - ...obsidianmd.configs.recommended, - - // Enable additional TypeScript rules for PR issues "@typescript-eslint/require-await": "error", "@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/no-namespace": "error", @@ -63,57 +53,35 @@ export default [ "@typescript-eslint/switch-exhaustiveness-check": "error", "@typescript-eslint/no-explicit-any": "error", - // ESLint directive comment rules - "eslint-comments/require-description": "error", - "eslint-comments/no-unused-disable": "error", - "eslint-comments/no-restricted-disable": [ + "@eslint-community/eslint-comments/require-description": "error", + "@eslint-community/eslint-comments/no-unused-disable": "error", + "@eslint-community/eslint-comments/no-restricted-disable": [ "error", "@typescript-eslint/no-explicit-any", - "no-restricted-globals" + "no-restricted-globals", ], - // Console usage (allow warn, error, debug only) "no-console": ["error", { allow: ["warn", "error", "debug"] }], - // Restricted globals - // Note: fetch is intentionally not restricted here because this plugin legitimately needs - // fetch for streaming and AbortSignal support, which requestUrl doesn't provide "no-restricted-globals": [ "error", - { - name: "app", - message: "Avoid using the global app object. Instead use the reference provided by your plugin instance.", - }, - { - name: "localStorage", - message: "Prefer `App#saveLocalStorage` / `App#loadLocalStorage` functions to write / read localStorage data that's unique to a vault." - } + { name: "app", message: "Avoid using the global app object. Instead use the reference provided by your plugin instance." }, + { name: "localStorage", message: "Prefer `App#saveLocalStorage` / `App#loadLocalStorage` functions to write / read localStorage data that's unique to a vault." }, ], - // Restricted imports "no-restricted-imports": [ "error", - { - name: "axios", - message: "Use the built-in `requestUrl` function instead of `axios`.", - }, - { - name: "superagent", - message: "Use the built-in `requestUrl` function instead of `superagent`.", - }, - { - name: "got", - message: "Use the built-in `requestUrl` function instead of `got`.", - }, - { - name: "node-fetch", - message: "Use the built-in `requestUrl` function instead of `node-fetch`.", - }, - { - name: "moment", - message: "The 'moment' package is bundled with Obsidian. Please import it from 'obsidian' instead.", - }, + { name: "axios", message: "Use the built-in `requestUrl` function instead of `axios`." }, + { name: "superagent", message: "Use the built-in `requestUrl` function instead of `superagent`." }, + { name: "got", message: "Use the built-in `requestUrl` function instead of `got`." }, + { name: "node-fetch", message: "Use the built-in `requestUrl` function instead of `node-fetch`." }, + { name: "moment", message: "The 'moment' package is bundled with Obsidian. Please import it from 'obsidian' instead." }, ], - } - } -]; \ No newline at end of file + }, + }, + + { + files: ["**/*.js", "**/*.mjs", "**/*.cjs"], + extends: [tseslint.configs.disableTypeChecked], + }, +]); \ No newline at end of file diff --git a/main.ts b/main.ts index 3469ed5..366020d 100644 --- a/main.ts +++ b/main.ts @@ -56,7 +56,7 @@ export default class VaultkeeperAIPlugin extends Plugin { public async activateMainView() { const { workspace } = this.app; - let leaf: WorkspaceLeaf | null = null; + let leaf: WorkspaceLeaf | null; const leaves = workspace.getLeavesOfType(VIEW_TYPE_MAIN); if (leaves.length > 0) { @@ -74,10 +74,8 @@ export default class VaultkeeperAIPlugin extends Plugin { public async activateDiffView(diffString: string, config: Diff2HtmlUIConfig) { const { workspace } = this.app; - let leaf: WorkspaceLeaf | null = null; const leaves = workspace.getLeavesOfType(VIEW_TYPE_DIFF); - - leaf = leaves.length > 0 ? leaves[0] : workspace.getLeaf("tab"); + const leaf = leaves.length > 0 ? leaves[0] : workspace.getLeaf("tab"); await leaf?.setViewState({ type: VIEW_TYPE_DIFF, diff --git a/package-lock.json b/package-lock.json index e28d49d..ab412e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,20 +39,20 @@ "zod": "^4.3.6" }, "devDependencies": { - "@eslint/js": "^9.39.2", + "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1", + "@eslint/js": "^10.0.1", "@testing-library/svelte": "^5.3.1", "@types/express": "^5.0.6", "@types/node": "^25.6.0", "@types/path-browserify": "^1.0.3", - "@typescript-eslint/eslint-plugin": "8.58.2", - "@typescript-eslint/parser": "8.58.2", + "@typescript-eslint/eslint-plugin": "8.59.0", + "@typescript-eslint/parser": "8.59.0", "@vitest/ui": "^4.1.4", "builtin-modules": "5.1.0", "esbuild": "^0.28.0", "esbuild-svelte": "^0.9.4", - "eslint": "^9.39.2", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-obsidianmd": "^0.2.3", + "eslint": "^10.2.1", + "eslint-plugin-obsidianmd": "^0.2.4", "happy-dom": "^20.9.0", "obsidian": "latest", "svelte": "^5.55.4", @@ -628,6 +628,26 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-plugin-eslint-comments": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-4.7.1.tgz", + "integrity": "sha512-Ql2nJFwA8wUGpILYGOQaT1glPsmvEwE0d+a+l7AALLzQvInqdbXJdx7aSu0DpUX9dB1wMVBMhm99/++S3MdEtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^4.0.0", + "ignore": "^7.0.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", @@ -658,75 +678,44 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", - "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.7", + "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", - "minimatch": "^3.1.5" + "minimatch": "^10.2.4" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", + "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0" + "@eslint/core": "^1.2.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/eslintrc": { @@ -771,6 +760,37 @@ "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -795,16 +815,24 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", - "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/@eslint/json": { @@ -813,7 +841,6 @@ "integrity": "sha512-rvR/EZtvUG3p9uqrSmcDJPYSH7atmWr0RnFWN6m917MAPx82+zQgPUmDu0whPFG6XTyM0vB/hR6c1Q63OaYtCQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@eslint/core": "^0.17.0", "@eslint/plugin-kit": "^0.4.1", @@ -824,17 +851,20 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "node_modules/@eslint/json/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit": { + "node_modules/@eslint/json/node_modules/@eslint/plugin-kit": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", @@ -848,6 +878,30 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", + "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, "node_modules/@google/genai": { "version": "1.50.1", "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.50.1.tgz", @@ -929,7 +983,6 @@ "integrity": "sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=18" } @@ -1006,44 +1059,6 @@ "license": "MIT", "peer": true }, - "node_modules/@microsoft/eslint-plugin-sdl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/eslint-plugin-sdl/-/eslint-plugin-sdl-1.1.0.tgz", - "integrity": "sha512-dxdNHOemLnBhfY3eByrujX9KyLigcNtW8sU+axzWv5nLGcsSBeKW2YYyTpfPo1hV8YPOmIGnfA4fZHyKVtWqBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-plugin-n": "17.10.3", - "eslint-plugin-react": "7.37.3", - "eslint-plugin-security": "1.4.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "eslint": "^9" - } - }, - "node_modules/@microsoft/eslint-plugin-sdl/node_modules/eslint-plugin-security": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz", - "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "safe-regex": "^1.1.0" - } - }, - "node_modules/@microsoft/eslint-plugin-sdl/node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ret": "~0.1.10" - } - }, "node_modules/@napi-rs/canvas": { "version": "0.1.99", "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.99.tgz", @@ -1328,10 +1343,48 @@ "@emnapi/runtime": "^1.7.1" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@oxc-project/types": { - "version": "0.124.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz", - "integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==", + "version": "0.126.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.126.0.tgz", + "integrity": "sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==", "dev": true, "license": "MIT", "funding": { @@ -1435,9 +1488,9 @@ "license": "BSD-3-Clause" }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.16.tgz", + "integrity": "sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==", "cpu": [ "arm64" ], @@ -1452,9 +1505,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.16.tgz", + "integrity": "sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==", "cpu": [ "arm64" ], @@ -1469,9 +1522,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz", - "integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.16.tgz", + "integrity": "sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==", "cpu": [ "x64" ], @@ -1486,9 +1539,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz", - "integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.16.tgz", + "integrity": "sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==", "cpu": [ "x64" ], @@ -1503,9 +1556,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz", - "integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.16.tgz", + "integrity": "sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==", "cpu": [ "arm" ], @@ -1520,9 +1573,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.16.tgz", + "integrity": "sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==", "cpu": [ "arm64" ], @@ -1540,9 +1593,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz", - "integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.16.tgz", + "integrity": "sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==", "cpu": [ "arm64" ], @@ -1560,9 +1613,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.16.tgz", + "integrity": "sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==", "cpu": [ "ppc64" ], @@ -1580,9 +1633,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.16.tgz", + "integrity": "sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==", "cpu": [ "s390x" ], @@ -1600,9 +1653,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.16.tgz", + "integrity": "sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==", "cpu": [ "x64" ], @@ -1620,9 +1673,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz", - "integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.16.tgz", + "integrity": "sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==", "cpu": [ "x64" ], @@ -1640,9 +1693,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.16.tgz", + "integrity": "sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==", "cpu": [ "arm64" ], @@ -1657,9 +1710,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz", - "integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.16.tgz", + "integrity": "sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==", "cpu": [ "wasm32" ], @@ -1669,16 +1722,16 @@ "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", - "@napi-rs/wasm-runtime": "^1.1.3" + "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { - "node": ">=14.0.0" + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz", - "integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.16.tgz", + "integrity": "sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==", "cpu": [ "arm64" ], @@ -1693,9 +1746,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz", - "integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.16.tgz", + "integrity": "sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==", "cpu": [ "x64" ], @@ -1710,9 +1763,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz", - "integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.16.tgz", + "integrity": "sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==", "dev": true, "license": "MIT" }, @@ -2039,6 +2092,13 @@ "@types/json-schema": "*" } }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -2220,17 +2280,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.2.tgz", - "integrity": "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.0.tgz", + "integrity": "sha512-HyAZtpdkgZwpq8Sz3FSUvCR4c+ScbuWa9AksK2Jweub7w4M3yTz4O11AqVJzLYjy/B9ZWPyc81I+mOdJU/bDQw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/type-utils": "8.58.2", - "@typescript-eslint/utils": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/type-utils": "8.59.0", + "@typescript-eslint/utils": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2243,22 +2303,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.58.2", + "@typescript-eslint/parser": "^8.59.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.2.tgz", - "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.0.tgz", + "integrity": "sha512-TI1XGwKbDpo9tRW8UDIXCOeLk55qe9ZFGs8MTKU6/M08HWTw52DD/IYhfQtOEhEdPhLMT26Ka/x7p70nd3dzDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "debug": "^4.4.3" }, "engines": { @@ -2274,14 +2334,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.2.tgz", - "integrity": "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.0.tgz", + "integrity": "sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.58.2", - "@typescript-eslint/types": "^8.58.2", + "@typescript-eslint/tsconfig-utils": "^8.59.0", + "@typescript-eslint/types": "^8.59.0", "debug": "^4.4.3" }, "engines": { @@ -2296,14 +2356,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.2.tgz", - "integrity": "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.0.tgz", + "integrity": "sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2" + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2314,9 +2374,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz", - "integrity": "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.0.tgz", + "integrity": "sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==", "dev": true, "license": "MIT", "engines": { @@ -2331,15 +2391,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.2.tgz", - "integrity": "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.0.tgz", + "integrity": "sha512-3TRiZaQSltGqGeNrJzzr1+8YcEobKH9rHnqIp/1psfKFmhRQDNMGP5hBufanYTGznwShzVLs3Mz+gDN7HkWfXg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/utils": "8.58.2", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/utils": "8.59.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2356,9 +2416,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.2.tgz", - "integrity": "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.0.tgz", + "integrity": "sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==", "dev": true, "license": "MIT", "engines": { @@ -2370,16 +2430,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.2.tgz", - "integrity": "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.0.tgz", + "integrity": "sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.58.2", - "@typescript-eslint/tsconfig-utils": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/project-service": "8.59.0", + "@typescript-eslint/tsconfig-utils": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/visitor-keys": "8.59.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2398,16 +2458,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.2.tgz", - "integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.0.tgz", + "integrity": "sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2" + "@typescript-eslint/scope-manager": "8.59.0", + "@typescript-eslint/types": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2422,13 +2482,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.2.tgz", - "integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.0.tgz", + "integrity": "sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", + "@typescript-eslint/types": "8.59.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -2681,16 +2741,13 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -3011,6 +3068,19 @@ "node": "18 || 20 || >=22" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3134,6 +3204,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -3925,33 +4011,30 @@ } }, "node_modules/eslint": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", - "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz", + "integrity": "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.2", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.5", - "@eslint/js": "9.39.4", - "@eslint/plugin-kit": "^0.4.1", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.5.5", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", - "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -3961,8 +4044,7 @@ "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.5", + "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -3970,7 +4052,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" @@ -4084,131 +4166,6 @@ "eslint": ">=8" } }, - "node_modules/eslint-plugin-eslint-comments": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", - "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5", - "ignore": "^5.0.5" - }, - "engines": { - "node": ">=6.5.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-eslint-comments/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint-plugin-eslint-comments/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", - "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-json-schema-validator": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-json-schema-validator/-/eslint-plugin-json-schema-validator-5.1.0.tgz", @@ -4377,25 +4334,41 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/eslint-plugin-no-unsanitized": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.1.5.tgz", + "integrity": "sha512-MSB4hXPVFQrI8weqzs6gzl7reP2k/qSjtCoL2vUMSDejIIq9YL1ZKvq5/ORBXab/PvfBBrWO2jWviYpL+4Ghfg==", + "dev": true, + "license": "MPL-2.0", + "peerDependencies": { + "eslint": "^9 || ^10" + } + }, "node_modules/eslint-plugin-obsidianmd": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-obsidianmd/-/eslint-plugin-obsidianmd-0.2.3.tgz", - "integrity": "sha512-UJ2mfx7I0CCJhejaN33F48sNfIoPRJYGb1744kY4lajoRTquaQSOdVYgRzVk+mz/sJS2OPK35PJPwC/1a3J+yQ==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-obsidianmd/-/eslint-plugin-obsidianmd-0.2.4.tgz", + "integrity": "sha512-5iO3WJ2ZWN4AqBLslS83KsdcEYbT6SiDgRkB9nfM/pM4N87BHBTmScANcSOMiSHDnN1h/vUvWw2scJslVddPVQ==", "dev": true, "license": "MIT", "dependencies": { + "@eslint/js": "^9.30.1", + "@eslint/json": "0.14.0", "@microsoft/eslint-plugin-sdl": "^1.1.0", "@types/eslint": "9.6.1", "@types/node": "20.12.12", + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/utils": "8.33.1", "eslint": ">=9.0.0 <10.0.0", "eslint-plugin-depend": "1.3.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-json-schema-validator": "5.1.0", + "eslint-plugin-no-unsanitized": "^4.1.5", "eslint-plugin-security": "2.1.1", "globals": "14.0.0", "obsidian": "1.12.3", "semver": "^7.7.4", - "typescript": "5.4.5" + "typescript": "5.4.5", + "typescript-eslint": "^8.35.1" }, "bin": { "eslint-plugin-obsidian": "dist/lib/index.js" @@ -4411,6 +4384,136 @@ "typescript-eslint": "^8.35.1" } }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@microsoft/eslint-plugin-sdl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@microsoft/eslint-plugin-sdl/-/eslint-plugin-sdl-1.1.0.tgz", + "integrity": "sha512-dxdNHOemLnBhfY3eByrujX9KyLigcNtW8sU+axzWv5nLGcsSBeKW2YYyTpfPo1hV8YPOmIGnfA4fZHyKVtWqBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-plugin-n": "17.10.3", + "eslint-plugin-react": "7.37.3", + "eslint-plugin-security": "1.4.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "eslint": "^9" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@microsoft/eslint-plugin-sdl/node_modules/eslint-plugin-security": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz", + "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-regex": "^1.1.0" + } + }, "node_modules/eslint-plugin-obsidianmd/node_modules/@types/node": { "version": "20.12.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", @@ -4421,28 +4524,304 @@ "undici-types": "~5.26.4" } }, - "node_modules/eslint-plugin-obsidianmd/node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "node_modules/eslint-plugin-obsidianmd/node_modules/@typescript-eslint/project-service": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.1.tgz", + "integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==", "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.33.1", + "@typescript-eslint/types": "^8.33.1", + "debug": "^4.3.4" }, "engines": { - "node": ">=14.17" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/eslint-plugin-obsidianmd/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "node_modules/eslint-plugin-obsidianmd/node_modules/@typescript-eslint/scope-manager": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz", + "integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/visitor-keys": "8.33.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz", + "integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@typescript-eslint/types": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz", + "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz", + "integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.33.1", + "@typescript-eslint/tsconfig-utils": "8.33.1", + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/visitor-keys": "8.33.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@typescript-eslint/utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.33.1", + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/typescript-estree": "8.33.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz", + "integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.33.1", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, - "node_modules/eslint-plugin-react": { + "node_modules/eslint-plugin-obsidianmd/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-react": { "version": "7.37.3", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.3.tgz", "integrity": "sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA==", @@ -4475,14 +4854,7 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-plugin-react/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-react/node_modules/brace-expansion": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", @@ -4493,7 +4865,7 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-react/node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", @@ -4506,7 +4878,7 @@ "node": "*" } }, - "node_modules/eslint-plugin-react/node_modules/semver": { + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-plugin-react/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", @@ -4516,6 +4888,135 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/eslint-plugin-obsidianmd/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint-plugin-security": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.1.tgz", @@ -4527,17 +5028,19 @@ } }, "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4556,32 +5059,14 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4597,19 +5082,6 @@ "node": ">= 4" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/esm-env": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", @@ -4618,31 +5090,31 @@ "license": "MIT" }, "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4797,6 +5269,36 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4828,6 +5330,16 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -4906,6 +5418,19 @@ "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -5978,6 +6503,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", @@ -7142,6 +7677,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -7733,6 +8278,33 @@ ], "license": "MIT" }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", @@ -8516,19 +9088,6 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -8620,6 +9179,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -8997,15 +9577,26 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rolldown": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz", - "integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==", + "version": "1.0.0-rc.16", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.16.tgz", + "integrity": "sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.124.0", - "@rolldown/pluginutils": "1.0.0-rc.15" + "@oxc-project/types": "=0.126.0", + "@rolldown/pluginutils": "1.0.0-rc.16" }, "bin": { "rolldown": "bin/cli.mjs" @@ -9014,21 +9605,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.15", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", - "@rolldown/binding-darwin-x64": "1.0.0-rc.15", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" + "@rolldown/binding-android-arm64": "1.0.0-rc.16", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.16", + "@rolldown/binding-darwin-x64": "1.0.0-rc.16", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.16", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.16", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.16", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.16", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.16", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.16", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.16", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.16", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.16", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.16", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.16", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.16" } }, "node_modules/router": { @@ -9047,6 +9638,30 @@ "node": ">= 18" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -9061,15 +9676,15 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, @@ -9891,6 +10506,19 @@ "node": ">=14.0.0" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -10142,17 +10770,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.2.tgz", - "integrity": "sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==", + "version": "8.59.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.0.tgz", + "integrity": "sha512-BU3ONW9X+v90EcCH9ZS6LMackcVtxRLlI3XrYyqZIwVSHIk7Qf7bFw1z0M9Q0IUxhTMZCf8piY9hTYaNEIASrw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.58.2", - "@typescript-eslint/parser": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/utils": "8.58.2" + "@typescript-eslint/eslint-plugin": "8.59.0", + "@typescript-eslint/parser": "8.59.0", + "@typescript-eslint/typescript-estree": "8.59.0", + "@typescript-eslint/utils": "8.59.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10425,17 +11052,17 @@ } }, "node_modules/vite": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz", - "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==", + "version": "8.0.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.9.tgz", + "integrity": "sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", - "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.15", - "tinyglobby": "^0.2.15" + "postcss": "^8.5.10", + "rolldown": "1.0.0-rc.16", + "tinyglobby": "^0.2.16" }, "bin": { "vite": "bin/vite.js" diff --git a/package.json b/package.json index d4eb2c7..fa8ee19 100644 --- a/package.json +++ b/package.json @@ -20,20 +20,20 @@ "author": "", "license": "MIT", "devDependencies": { - "@eslint/js": "^9.39.2", + "@eslint/js": "^10.0.1", "@testing-library/svelte": "^5.3.1", "@types/express": "^5.0.6", "@types/node": "^25.6.0", "@types/path-browserify": "^1.0.3", - "@typescript-eslint/eslint-plugin": "8.58.2", - "@typescript-eslint/parser": "8.58.2", + "@typescript-eslint/eslint-plugin": "8.59.0", + "@typescript-eslint/parser": "8.59.0", "@vitest/ui": "^4.1.4", "builtin-modules": "5.1.0", "esbuild": "^0.28.0", "esbuild-svelte": "^0.9.4", - "eslint": "^9.39.2", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-obsidianmd": "^0.2.3", + "eslint": "^10.2.1", + "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1", + "eslint-plugin-obsidianmd": "^0.2.4", "happy-dom": "^20.9.0", "obsidian": "latest", "svelte": "^5.55.4",