From ba442d20ce108b2f9cd0de28a6f7b7e1336f8105 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 15 Jul 2025 11:57:22 +0000 Subject: [PATCH 01/47] Update manifest.json to version --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index b84cbdd..83a74ca 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes", - "version": "1.8.15", + "version": "1.8.16", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From 9a1e5773a04bdd7e202367c7c42a2f9c41818399 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Fri, 18 Jul 2025 18:01:26 +0200 Subject: [PATCH 02/47] Update obsidian-folder-overview --- src/obsidian-folder-overview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 2b6539f..e54c4a2 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 2b6539f1e7c4a71b5b766fd18ea7061eef5d12ba +Subproject commit e54c4a2a27a606416cffbe3aef1a75cd779b4f43 From e46191d13773f645506484d5df8d8c67b46e4dbf Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Fri, 18 Jul 2025 18:10:48 +0200 Subject: [PATCH 03/47] Update link list in the background --- src/main.ts | 14 +++++++++++++- src/settings/FolderOverviewSettings.ts | 4 ++-- src/settings/SettingsTab.ts | 12 +++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/main.ts b/src/main.ts index d1cf6e0..db44354 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,5 @@ -import { Plugin, TFile, TFolder, TAbstractFile, MarkdownPostProcessorContext, parseYaml, Notice, Keymap, WorkspaceLeaf, requireApiVersion, Platform } from 'obsidian'; +import { Plugin, TFile, TFolder, TAbstractFile, MarkdownPostProcessorContext, parseYaml, Notice, Keymap, WorkspaceLeaf, requireApiVersion, Platform, debounce } from 'obsidian'; import { DEFAULT_SETTINGS, FolderNotesSettings, SettingsTab } from './settings/SettingsTab'; import { Commands } from './Commands'; import { FileExplorerWorkspaceLeaf } from './globals'; @@ -20,6 +20,8 @@ import { FileExplorerView, InternalPlugin } from 'obsidian-typings'; import { FOLDER_OVERVIEW_VIEW, FolderOverviewView } from './obsidian-folder-overview/src/view'; import { registerOverviewCommands } from './obsidian-folder-overview/src/Commands'; import { updateOverviewView, updateViewDropdown } from './obsidian-folder-overview/src/main'; +import { FvIndexDB } from './obsidian-folder-overview/src/utils/IndexDB'; +import { updateAllOverviews } from './obsidian-folder-overview/src/utils/functions'; export default class FolderNotesPlugin extends Plugin { observer: MutationObserver; @@ -34,6 +36,7 @@ export default class FolderNotesPlugin extends Plugin { tabManager: TabManager; settingsOpened = false; askModalCurrentlyOpen = false; + fvIndexDB: FvIndexDB; private fileExplorerPlugin!: InternalPlugin; private fileExplorerView!: FileExplorerView; @@ -44,6 +47,7 @@ export default class FolderNotesPlugin extends Plugin { this.settingsTab = new SettingsTab(this.app, this); this.addSettingTab(this.settingsTab); this.saveSettings(); + this.fvIndexDB = new FvIndexDB(this); // Add CSS Classes document.body.classList.add('folder-notes-plugin'); @@ -128,6 +132,7 @@ export default class FolderNotesPlugin extends Plugin { this.registerEvent(this.app.vault.on('rename', (file: TAbstractFile, oldPath: string) => { handleRename(file, oldPath, this); + })); this.registerEvent(this.app.vault.on('delete', (file: TAbstractFile) => { @@ -230,6 +235,13 @@ export default class FolderNotesPlugin extends Plugin { }; } + handleVaultChange() { + if (!this.settings.fvGlobalSettings.autoUpdateLinks) return; + debounce(() => { + updateAllOverviews(this); + }, 2000, true)(); + } + handleFileExplorerClick(evt: MouseEvent) { const target = evt.target as HTMLElement; if (evt.shiftKey) return; diff --git a/src/settings/FolderOverviewSettings.ts b/src/settings/FolderOverviewSettings.ts index 69f1985..52e63d5 100644 --- a/src/settings/FolderOverviewSettings.ts +++ b/src/settings/FolderOverviewSettings.ts @@ -3,7 +3,7 @@ import { createOverviewSettings } from 'src/obsidian-folder-overview/src/setting export async function renderFolderOverview(settingsTab: SettingsTab) { const { plugin } = settingsTab; - const overviewSettings = plugin.settings.defaultOverview; + const defaultOverviewSettings = plugin.settings.defaultOverview; const containerEl = settingsTab.settingsPage; const pEl = containerEl.createEl('p', { text: 'Edit the default settings for new folder overviews, ', @@ -14,5 +14,5 @@ export async function renderFolderOverview(settingsTab: SettingsTab) { span.setAttr('style', `color: ${accentColor};`); pEl.appendChild(span); - createOverviewSettings(containerEl, overviewSettings, plugin, plugin.settings.defaultOverview, settingsTab.display, undefined, undefined, undefined, settingsTab); + createOverviewSettings(containerEl, defaultOverviewSettings, plugin, plugin.settings.defaultOverview, settingsTab.display, undefined, undefined, undefined, settingsTab); } diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index b1539af..881b537 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -3,7 +3,7 @@ import FolderNotesPlugin from '../main'; import { ExcludePattern } from 'src/ExcludeFolders/ExcludePattern'; import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; import { extractFolderName, getFolderNote } from '../functions/folderNoteFunctions'; -import { overviewSettings } from '../obsidian-folder-overview/src/FolderOverview'; +import { defaultOverviewSettings } from '../obsidian-folder-overview/src/FolderOverview'; import { renderGeneral } from './GeneralSettings'; import { renderFileExplorer } from './FileExplorerSettings'; import { renderPath } from './PathSettings'; @@ -41,7 +41,7 @@ export interface FolderNotesSettings { disableFolderHighlighting: boolean; storageLocation: 'insideFolder' | 'parentFolder' | 'vaultFolder'; syncDelete: boolean; - defaultOverview: overviewSettings; + defaultOverview: defaultOverviewSettings; useSubmenus: boolean; syncMove: boolean; frontMatterTitle: { @@ -76,6 +76,9 @@ export interface FolderNotesSettings { afterChangingTab: boolean; }, firstTimeInsertOverview: boolean; + fvGlobalSettings: { + autoUpdateLinks: boolean; + } } export const DEFAULT_SETTINGS: FolderNotesSettings = { @@ -194,6 +197,9 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = { afterChangingTab: true, }, firstTimeInsertOverview: true, + fvGlobalSettings: { + autoUpdateLinks: false, + }, }; export class SettingsTab extends PluginSettingTab { @@ -248,7 +254,7 @@ export class SettingsTab extends PluginSettingTab { } } - display(contentEl?: HTMLElement, yaml?: overviewSettings, plugin?: FolderNotesPlugin, defaultSettings?: boolean, display?: CallableFunction, el?: HTMLElement, ctx?: MarkdownPostProcessorContext, file?: TFile | null, settingsTab?: this) { + display(contentEl?: HTMLElement, yaml?: defaultOverviewSettings, plugin?: FolderNotesPlugin, defaultSettings?: boolean, display?: CallableFunction, el?: HTMLElement, ctx?: MarkdownPostProcessorContext, file?: TFile | null, settingsTab?: this) { plugin = this?.plugin ?? plugin; if (plugin) { plugin.settingsOpened = true; From cc2b15d8dbb75cdd61bb70bf0a936de629c4d6e1 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 19 Jul 2025 09:18:14 +0200 Subject: [PATCH 04/47] Fix folder highlight --- src/events/handleClick.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/handleClick.ts b/src/events/handleClick.ts index d5106e7..4bb35bd 100644 --- a/src/events/handleClick.ts +++ b/src/events/handleClick.ts @@ -5,11 +5,11 @@ import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions' import { addCSSClassToFileExplorerEl, removeCSSClassFromFileExplorerEL } from 'src/functions/styleFunctions'; export async function handleViewHeaderClick(event: MouseEvent, plugin: FolderNotesPlugin) { + if (!plugin.settings.openFolderNoteOnClickInPath) return; event.stopImmediatePropagation(); event.preventDefault(); event.stopPropagation(); if (!(event.target instanceof HTMLElement)) return; - if (!plugin.settings.openFolderNoteOnClickInPath) return; const folderPath = event.target.getAttribute('data-path'); if (!folderPath) { return; } From ffaa74faaa11be4a3facd1fcb43b5b512a40b102 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 19 Jul 2025 09:33:21 +0200 Subject: [PATCH 05/47] Update PathSettings.ts --- src/settings/PathSettings.ts | 46 +++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/settings/PathSettings.ts b/src/settings/PathSettings.ts index 7bf3e14..eb8499f 100644 --- a/src/settings/PathSettings.ts +++ b/src/settings/PathSettings.ts @@ -15,29 +15,31 @@ export async function renderPath(settingsTab: SettingsTab) { }) ); - new Setting(containerEl) - .setName('Open sidebar when opening a folder note through path (Mobile only)') - .setDesc('Open the sidebar when opening a folder note through the path on mobile') - .addToggle((toggle) => - toggle - .setValue(settingsTab.plugin.settings.openSidebar.mobile) - .onChange(async (value) => { - settingsTab.plugin.settings.openSidebar.mobile = value; - await settingsTab.plugin.saveSettings(); - }) - ); + if (settingsTab.plugin.settings.openFolderNoteOnClickInPath) { + new Setting(containerEl) + .setName('Open sidebar when opening a folder note through path (Mobile only)') + .setDesc('Open the sidebar when opening a folder note through the path on mobile') + .addToggle((toggle) => + toggle + .setValue(settingsTab.plugin.settings.openSidebar.mobile) + .onChange(async (value) => { + settingsTab.plugin.settings.openSidebar.mobile = value; + await settingsTab.plugin.saveSettings(); + }) + ); - new Setting(containerEl) - .setName('Open sidebar when opening a folder note through path (Desktop only)') - .setDesc('Open the sidebar when opening a folder note through the path on desktop') - .addToggle((toggle) => - toggle - .setValue(settingsTab.plugin.settings.openSidebar.desktop) - .onChange(async (value) => { - settingsTab.plugin.settings.openSidebar.desktop = value; - await settingsTab.plugin.saveSettings(); - }) - ); + new Setting(containerEl) + .setName('Open sidebar when opening a folder note through path (Desktop only)') + .setDesc('Open the sidebar when opening a folder note through the path on desktop') + .addToggle((toggle) => + toggle + .setValue(settingsTab.plugin.settings.openSidebar.desktop) + .onChange(async (value) => { + settingsTab.plugin.settings.openSidebar.desktop = value; + await settingsTab.plugin.saveSettings(); + }) + ); + } if (settingsTab.plugin.settings.frontMatterTitle.enabled) { new Setting(containerEl) From ccc3b24da767c3b27644820f2d7f570b9b354a81 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 19 Jul 2025 09:39:59 +0200 Subject: [PATCH 06/47] Update link list in the background --- src/main.ts | 16 +++++++++++----- src/settings/FolderOverviewSettings.ts | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/main.ts b/src/main.ts index db44354..24cd8c5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -111,10 +111,6 @@ export default class FolderNotesPlugin extends Plugin { this.hoverLinkTriggered = true; }); - this.registerEvent(this.app.vault.on('create', (file: TAbstractFile) => { - handleCreate(file, this); - })); - this.registerEvent(this.app.workspace.on('file-open', async (openFile: TFile | null) => { removeActiveFolder(this); @@ -130,13 +126,19 @@ export default class FolderNotesPlugin extends Plugin { setActiveFolder(folder.path, this); })); + this.registerEvent(this.app.vault.on('create', (file: TAbstractFile) => { + handleCreate(file, this); + this.handleVaultChange(); + })); + this.registerEvent(this.app.vault.on('rename', (file: TAbstractFile, oldPath: string) => { handleRename(file, oldPath, this); - + this.handleVaultChange(); })); this.registerEvent(this.app.vault.on('delete', (file: TAbstractFile) => { handleDelete(file, this); + this.handleVaultChange(); })); this.registerMarkdownCodeBlockProcessor('folder-overview', (source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) => { @@ -233,6 +235,10 @@ export default class FolderNotesPlugin extends Plugin { return originalHandleDrop.call(this, evt, ...args); }; + + if (this.settings.fvGlobalSettings.autoUpdateLinks) { + this.fvIndexDB.init(true); + } } handleVaultChange() { diff --git a/src/settings/FolderOverviewSettings.ts b/src/settings/FolderOverviewSettings.ts index 52e63d5..b06c6d4 100644 --- a/src/settings/FolderOverviewSettings.ts +++ b/src/settings/FolderOverviewSettings.ts @@ -1,3 +1,4 @@ +import { Setting } from 'obsidian'; import { SettingsTab } from './SettingsTab'; import { createOverviewSettings } from 'src/obsidian-folder-overview/src/settings'; @@ -5,6 +6,26 @@ export async function renderFolderOverview(settingsTab: SettingsTab) { const { plugin } = settingsTab; const defaultOverviewSettings = plugin.settings.defaultOverview; const containerEl = settingsTab.settingsPage; + + containerEl.createEl('h3', { text: 'Global settings' }); + new Setting(containerEl) + .setName('Auto-update links without opening the overview') + .setDesc('If enabled, the links that appear in the graph view will be updated even when you don\'t have the overview open somewhere.') + .addToggle((toggle) => + toggle + .setValue(plugin.settings.fvGlobalSettings.autoUpdateLinks) + .onChange(async (value) => { + plugin.settings.fvGlobalSettings.autoUpdateLinks = value; + await plugin.saveSettings(); + if (value) { + plugin.fvIndexDB.init(true); + } else { + plugin.fvIndexDB.active = false; + } + }) + ); + + containerEl.createEl('h3', { text: 'Overviews default settings' }); const pEl = containerEl.createEl('p', { text: 'Edit the default settings for new folder overviews, ', cls: 'setting-item-description', From b165b46aa7947285db5ff696197ede2228240cfa Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 19 Jul 2025 09:59:05 +0200 Subject: [PATCH 07/47] Supported file types add .base --- src/settings/GeneralSettings.ts | 3 ++- src/settings/SettingsTab.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/settings/GeneralSettings.ts b/src/settings/GeneralSettings.ts index 438860e..a588e84 100644 --- a/src/settings/GeneralSettings.ts +++ b/src/settings/GeneralSettings.ts @@ -130,7 +130,8 @@ export async function renderGeneral(settingsTab: SettingsTab) { const options = [ { value: 'md', label: 'Markdown' }, { value: 'canvas', label: 'Canvas' }, - { value: 'excalidraw', label: 'excalidraw' }, + { value: 'base', label: 'Bases' }, + { value: 'excalidraw', label: 'Excalidraw' }, { value: 'custom', label: 'Custom extension' }, ]; diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index 881b537..8c4ae84 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -141,7 +141,7 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = { path: true, }, settingsTab: 'general', - supportedFileTypes: ['md', 'canvas'], + supportedFileTypes: ['md', 'canvas', 'base'], boldName: false, boldNameInPath: false, cursiveName: false, From 4f018a915821f1d5f813095295e89865daf6f0fa Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 19 Jul 2025 11:15:39 +0200 Subject: [PATCH 08/47] Customize folder overview title size --- src/obsidian-folder-overview | 2 +- src/settings/SettingsTab.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index e54c4a2..77a54f4 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit e54c4a2a27a606416cffbe3aef1a75cd779b4f43 +Subproject commit 77a54f4146f6672c2818761b98203cc24881b567 diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index 8c4ae84..cd1077e 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -132,6 +132,7 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = { hideFolderOverview: false, useActualLinks: false, fmtpIntegration: false, + titleSize: 1, }, useSubmenus: true, syncMove: true, From f73515245cb22261077c691b7bcdcc646e8366fb Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 19 Jul 2025 11:19:18 +0200 Subject: [PATCH 09/47] Update Commands.ts --- src/Commands.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Commands.ts b/src/Commands.ts index 2155075..8e304e7 100644 --- a/src/Commands.ts +++ b/src/Commands.ts @@ -320,8 +320,6 @@ export class Commands { // item.setTitle('Manage excluded folder') // .setIcon('settings-2') // .onClick(() => { - // console.log('excludedFolder', excludedFolder) - // console.log('2', getExcludedFolder(this.plugin, file.path, false)) // if (excludedFolder instanceof ExcludedFolder) { // new ExcludedFolderSettings(this.plugin.app, this.plugin, excludedFolder).open(); // } else if (excludedFolder instanceof ExcludePattern) { From 2fdda5c1999df37588856d6e12a41ba728f6f595 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 19 Jul 2025 16:01:38 +0200 Subject: [PATCH 10/47] Update obsidian-folder-overview --- src/obsidian-folder-overview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 77a54f4..6189a6a 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 77a54f4146f6672c2818761b98203cc24881b567 +Subproject commit 6189a6abf7fe63b4f3aae32f673c1f644a8493ad From 2dad83ee7f175fe23807a2d35e67f821e857d06f Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Mon, 21 Jul 2025 09:15:06 +0200 Subject: [PATCH 11/47] Remove notices --- src/main.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 24cd8c5..8255ddc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -151,6 +151,7 @@ export default class FolderNotesPlugin extends Plugin { this.registerView(FOLDER_OVERVIEW_VIEW, (leaf: WorkspaceLeaf) => { return new FolderOverviewView(leaf, this); }); + if (this.app.plugins.getPlugin('obsidian-front-matter-title-plugin')) { this.fmtpHandler = new FrontMatterTitlePluginHandler(this); } @@ -237,7 +238,7 @@ export default class FolderNotesPlugin extends Plugin { }; if (this.settings.fvGlobalSettings.autoUpdateLinks) { - this.fvIndexDB.init(true); + this.fvIndexDB.init(false); } } From c87a8b67d9b988b8ef51e23eaede6d2871727806 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Mon, 21 Jul 2025 09:15:22 +0200 Subject: [PATCH 12/47] Update obsidian-folder-overview --- src/obsidian-folder-overview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 6189a6a..cb1e825 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 6189a6abf7fe63b4f3aae32f673c1f644a8493ad +Subproject commit cb1e825c96513b18011f424fc4c60188d0d08ba5 From 7f59b13788084cac36f1390a1ce003f710e1f293 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:34:20 +0200 Subject: [PATCH 13/47] Fix #267 --- src/main.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.ts b/src/main.ts index 8255ddc..440dea0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -147,6 +147,10 @@ export default class FolderNotesPlugin extends Plugin { } onLayoutReady() { + if (!this._loaded) { + return; + } + registerFileExplorerObserver(this); this.registerView(FOLDER_OVERVIEW_VIEW, (leaf: WorkspaceLeaf) => { return new FolderOverviewView(leaf, this); From a66847a38ed48a83aaaa289928073392b41e36b6 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:10:02 +0200 Subject: [PATCH 14/47] Update obsidian-folder-overview --- src/obsidian-folder-overview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index cb1e825..503ed5d 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit cb1e825c96513b18011f424fc4c60188d0d08ba5 +Subproject commit 503ed5db9d9ab0456fcae330e30a62cd923285d3 From 726476a42c18b86630d22f2a760499737dc05acd Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:27:36 +0200 Subject: [PATCH 15/47] Fix #268 --- src/events/handleClick.ts | 3 ++- src/main.ts | 8 +++++--- src/settings/GeneralSettings.ts | 6 ++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/events/handleClick.ts b/src/events/handleClick.ts index 4bb35bd..4b3035a 100644 --- a/src/events/handleClick.ts +++ b/src/events/handleClick.ts @@ -36,7 +36,8 @@ export async function handleViewHeaderClick(event: MouseEvent, plugin: FolderNot }); return; } else if (event.altKey || Keymap.isModEvent(event) === 'tab') { - if ((plugin.settings.altKey && event.altKey) || (plugin.settings.ctrlKey && Keymap.isModEvent(event) === 'tab')) { + const usedCtrl = Platform.isMacOS ? event.metaKey : event.ctrlKey; + if ((plugin.settings.altKey && event.altKey) || (usedCtrl && Keymap.isModEvent(event) === 'tab')) { await createFolderNote(plugin, folderPath, true, undefined, true); addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, plugin); removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, plugin); diff --git a/src/main.ts b/src/main.ts index 8255ddc..e2935cd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -278,9 +278,11 @@ export default class FolderNotesPlugin extends Plugin { const excludedFolder = getExcludedFolder(this, folderPath, true); if (excludedFolder?.disableFolderNote) return; + const usedCtrl = Platform.isMacOS ? evt.metaKey : evt.ctrlKey; + const folderNote = getFolderNote(this, folderPath); if (!folderNote && (evt.altKey || Keymap.isModEvent(evt) === 'tab')) { - if ((this.settings.altKey && evt.altKey) || (this.settings.ctrlKey && Keymap.isModEvent(evt) === 'tab')) { + if ((this.settings.altKey && evt.altKey) || (usedCtrl && this.settings.ctrlKey)) { createFolderNote(this, folderPath, true, undefined, true); addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, this); removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, this); @@ -289,10 +291,10 @@ export default class FolderNotesPlugin extends Plugin { } if (!(folderNote instanceof TFile)) return; - if (this.settings.openWithCtrl && !evt.ctrlKey) return; + if (this.settings.openWithCtrl && !usedCtrl) return; if (this.settings.openWithAlt && !evt.altKey) return; - if (!this.settings.enableCollapsing || evt.ctrlKey) { + if (!this.settings.enableCollapsing || usedCtrl) { evt.preventDefault(); evt.stopImmediatePropagation(); } diff --git a/src/settings/GeneralSettings.ts b/src/settings/GeneralSettings.ts index a588e84..495361e 100644 --- a/src/settings/GeneralSettings.ts +++ b/src/settings/GeneralSettings.ts @@ -254,10 +254,11 @@ export async function renderGeneral(settingsTab: SettingsTab) { .addDropdown((dropdown) => { if (!Platform.isMacOS) { dropdown.addOption('ctrl', 'Ctrl + Click'); + dropdown.addOption('alt', 'Alt + Click'); } else { dropdown.addOption('ctrl', 'Cmd + Click'); + dropdown.addOption('alt', 'Option + Click'); } - dropdown.addOption('alt', 'Alt + Click'); dropdown.setValue(settingsTab.plugin.settings.ctrlKey ? 'ctrl' : 'alt'); dropdown.onChange(async (value) => { settingsTab.plugin.settings.ctrlKey = value === 'ctrl'; @@ -274,10 +275,11 @@ export async function renderGeneral(settingsTab: SettingsTab) { dropdown.addOption('click', 'Mouse Click'); if (!Platform.isMacOS) { dropdown.addOption('ctrl', 'Ctrl + Click'); + dropdown.addOption('alt', 'Alt + Click'); } else { dropdown.addOption('ctrl', 'Cmd + Click'); + dropdown.addOption('alt', 'Option + Click'); } - dropdown.addOption('alt', 'Alt + Click'); if (settingsTab.plugin.settings.openByClick) { dropdown.setValue('click'); } else if (settingsTab.plugin.settings.openWithCtrl) { From eedbd8fca9916d769847baec4036f05a191298cf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Jul 2025 08:40:37 +0000 Subject: [PATCH 16/47] Update manifest-beta.json to version 1.8.17-0-beta in main branch --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index 95ff939..4cb7301 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes beta", - "version": "1.8.5-3-beta", + "version": "1.8.17-0-beta", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From 247c252ef88f747b07e7ab286b615e5cbffed5f9 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 26 Jul 2025 10:11:55 +0200 Subject: [PATCH 17/47] Support editing folder overview in callout --- src/obsidian-folder-overview | 2 +- styles.css | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 503ed5d..36548fd 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 503ed5db9d9ab0456fcae330e30a62cd923285d3 +Subproject commit 36548fdaf0b63e66a7c4c891347b788d38cf7f72 diff --git a/styles.css b/styles.css index 83abedf..1bfa9ea 100644 --- a/styles.css +++ b/styles.css @@ -120,6 +120,7 @@ body:not(.disable-folder-highlight) .tree-item-self.fn-is-active { } .cm-line:has(.fv-link-list-item), +li:has(.fv-link-list-item), .el-ul:has(.fv-link-list-item), .cm-line:has(.fv-link-list-start), .cm-line:has(.fv-link-list-end), From e87aec28c14d1565c6cf594b03a798858ec3578a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 26 Jul 2025 08:12:20 +0000 Subject: [PATCH 18/47] Update manifest-beta.json to version 1.8.17-1-beta in main branch --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index 4cb7301..60be061 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes beta", - "version": "1.8.17-0-beta", + "version": "1.8.17-1-beta", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From 86288080c893c4c8728bb9688ec0dba15674673f Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 26 Jul 2025 10:16:19 +0200 Subject: [PATCH 19/47] Update SettingsTab.ts --- src/settings/SettingsTab.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index cd1077e..15d62ab 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -133,6 +133,7 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = { useActualLinks: false, fmtpIntegration: false, titleSize: 1, + isInCallout: false, }, useSubmenus: true, syncMove: true, From 2504d69c3188bbae3b8491aa5971a61211994d65 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 26 Jul 2025 10:16:21 +0200 Subject: [PATCH 20/47] Update obsidian-folder-overview --- src/obsidian-folder-overview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 36548fd..f1d2495 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 36548fdaf0b63e66a7c4c891347b788d38cf7f72 +Subproject commit f1d24952999f23e2912c7e6c2da4bd53325d2402 From b0955915fbd99cc7c2d524ebb1cfb15a7da5d03d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 26 Jul 2025 08:18:48 +0000 Subject: [PATCH 21/47] Update manifest-beta.json to version 1.8.17-2-beta in main branch --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index 60be061..c97ba08 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes beta", - "version": "1.8.17-1-beta", + "version": "1.8.17-2-beta", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From d98958c7bd8651ade286975846e4d57a32934c31 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sun, 27 Jul 2025 11:33:21 +0200 Subject: [PATCH 22/47] Eslint code style fixes no. 1 --- .eslintignore | 7 - .eslintrc | 150 -- eslint.config.mts | 158 ++ package-lock.json | 2173 ++++++++++------- package.json | 7 +- src/Commands.ts | 23 +- src/ExcludeFolders/ExcludeFolder.ts | 2 +- src/ExcludeFolders/ExcludePattern.ts | 2 +- src/ExcludeFolders/WhitelistFolder.ts | 2 +- src/ExcludeFolders/WhitelistPattern.ts | 2 +- .../functions/folderFunctions.ts | 22 +- .../functions/patternFunctions.ts | 8 +- .../functions/whitelistFolderFunctions.ts | 10 +- .../functions/whitelistPatternFunctions.ts | 8 +- .../modals/ExcludeFolderSettings.ts | 21 +- src/ExcludeFolders/modals/PatternSettings.ts | 19 +- .../modals/WhitelistFolderSettings.ts | 21 +- .../modals/WhitelistPatternSettings.ts | 17 +- .../modals/WhitelistedFoldersSettings.ts | 7 +- src/events/FrontMatterTitle.ts | 12 +- src/events/MutationObserver.ts | 4 +- src/events/TabManager.ts | 5 +- src/events/handleClick.ts | 2 +- src/events/handleCreate.ts | 5 +- src/events/handleDelete.ts | 5 +- src/events/handleRename.ts | 15 +- src/functions/excalidraw.ts | 4 +- src/functions/folderNoteFunctions.ts | 37 +- src/functions/styleFunctions.ts | 8 +- src/functions/utils.ts | 18 +- src/globals.d.ts | 2 +- src/main.ts | 20 +- src/modals/AddSupportedFileType.ts | 9 +- src/modals/AskForExtension.ts | 5 +- src/modals/DeleteConfirmation.ts | 5 +- src/modals/ExistingNote.ts | 5 +- src/modals/FolderName.ts | 7 +- src/modals/NewFolderName.ts | 5 +- src/obsidian-folder-overview | 2 +- src/settings/ExcludedFoldersSettings.ts | 2 +- src/settings/FileExplorerSettings.ts | 28 +- src/settings/FolderOverviewSettings.ts | 4 +- src/settings/GeneralSettings.ts | 46 +- src/settings/PathSettings.ts | 16 +- src/settings/SettingsTab.ts | 21 +- src/settings/modals/BackupWarning.ts | 2 +- src/settings/modals/CreateFnForEveryFolder.ts | 7 +- src/settings/modals/RenameFns.ts | 6 +- src/suggesters/FileSuggester.ts | 7 +- src/suggesters/FolderSuggester.ts | 5 +- src/suggesters/Suggest.ts | 20 +- src/suggesters/TemplateSuggester.ts | 11 +- src/template.ts | 11 +- 53 files changed, 1746 insertions(+), 1274 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc create mode 100644 eslint.config.mts diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 9e519d6..0000000 --- a/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -npm node_modules -build -*.js -*.json -*.md -*.css -LICENSE \ No newline at end of file diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 6d26f2d..0000000 --- a/.eslintrc +++ /dev/null @@ -1,150 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "env": { - "node": true - }, - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" - ], - "parserOptions": { - "sourceType": "module" - }, - "rules": { - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none" - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/ban-ts-comment": "off", - "no-prototype-builtins": "off", - "@typescript-eslint/no-empty-function": "off", - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "consistent-return": "off", - "quotes": [ - "error", - "single", - { - "avoidEscape": true - } - ], - "@typescript-eslint/ban-types": [ - "error", - { - "types": { - "Function": false - }, - "extendDefaults": true - } - ], - "no-mixed-spaces-and-tabs": "error", - "indent": [ - "error", - "tab", - { - "SwitchCase": 1 - } - ], - "arrow-parens": [ - "error", - "always" - ], - "eol-last": [ - "error", - "always" - ], - "func-call-spacing": [ - "error", - "never" - ], - "comma-dangle": [ - "error", - "always-multiline" - ], - "no-multi-spaces": "error", - "no-trailing-spaces": "error", - "no-whitespace-before-property": "off", - "semi": [ - "error", - "always" - ], - "semi-style": [ - "error", - "last" - ], - "space-in-parens": [ - "error", - "never" - ], - "block-spacing": [ - "error", - "always" - ], - "object-curly-spacing": [ - "error", - "always" - ], - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "spaced-comment": [ - "error", - "always", - { - "markers": [ - "!" - ] - } - ], - "yoda": "error", - "prefer-destructuring": [ - "error", - { - "object": false, - "array": false - } - ], - "operator-assignment": [ - "error", - "always" - ], - "no-useless-computed-key": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-invalid-regexp": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-duplicate-imports": "error", - "no-extra-semi": "error", - "dot-notation": "error", - "no-useless-escape": [ - "error" - ] - } -} \ No newline at end of file diff --git a/eslint.config.mts b/eslint.config.mts new file mode 100644 index 0000000..bb047f9 --- /dev/null +++ b/eslint.config.mts @@ -0,0 +1,158 @@ +import tseslint from "typescript-eslint"; + +export default [ + { + files: ["**/*.ts"], + languageOptions: { + parser: tseslint.parser, + parserOptions: { + sourceType: "module" + } + }, + ignores: [ + "**/node_modules/**", + "**/dist/**", + ], + plugins: { + "@typescript-eslint": tseslint.plugin + }, + rules: { + "no-unused-vars": "off", + "quotes": [ + "error", + "single", + { + "avoidEscape": true + } + ], + "no-mixed-spaces-and-tabs": "error", + "indent": [ + "error", + "tab", + { + "SwitchCase": 1 + } + ], + "arrow-parens": [ + "error", + "always" + ], + "eol-last": [ + "error", + "always" + ], + "func-call-spacing": [ + "error", + "never" + ], + "comma-dangle": [ + "error", + "always-multiline" + ], + "no-multi-spaces": "error", + "no-trailing-spaces": "error", + "no-whitespace-before-property": "off", + "semi": [ + "error", + "always" + ], + "semi-style": [ + "error", + "last" + ], + "space-in-parens": [ + "error", + "never" + ], + "block-spacing": [ + "error", + "always" + ], + "object-curly-spacing": [ + "error", + "always" + ], + "eqeqeq": [ + "error", + "always", + { + "null": "ignore" + } + ], + "spaced-comment": [ + "error", + "always", + { + "markers": [ + "!" + ] + } + ], + "yoda": "error", + "prefer-destructuring": [ + "error", + { + "object": true, + "array": false + } + ], + "operator-assignment": [ + "error", + "always" + ], + "no-useless-computed-key": "error", + "no-unneeded-ternary": [ + "error", + { + "defaultAssignment": false + } + ], + "no-invalid-regexp": "error", + "no-constant-condition": [ + "error", + { + "checkLoops": false + } + ], + "no-duplicate-imports": "error", + "no-extra-semi": "error", + "dot-notation": "error", + "no-useless-escape": "error", + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/consistent-type-imports': 'error', + '@typescript-eslint/consistent-type-definitions': [ + 'error', + 'interface'], + '@typescript-eslint/explicit-function-return-type': 'warn', + '@typescript-eslint/ban-ts-comment': 'warn', + 'array-bracket-spacing': [ + 'error', 'never'], + 'linebreak-style': [ + 'error', + 'unix' + ], + 'no-nested-ternary': 'error', + 'no-shadow': 'error', + 'no-return-await': 'error', + 'no-else-return': 'error', + 'no-empty-function': 'warn', + 'complexity': [ + 'warn', + 10 + ], + 'max-len': [ + 'warn', { + code: 100 + } + ], + 'no-inline-comments': 'warn', + 'no-magic-numbers': [ + 'warn', { + ignore: [0, 1], + enforceConst: true + } + ], + } + } +]; diff --git a/package-lock.json b/package-lock.json index c89fed7..7886651 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,16 +12,21 @@ "@popperjs/core": "^2.11.6" }, "devDependencies": { + "@eslint/js": "^9.32.0", "@types/node": "^16.11.6", "@typescript-eslint/eslint-plugin": "5.29.0", "@typescript-eslint/parser": "5.29.0", "builtin-modules": "3.3.0", "esbuild": "0.14.47", + "eslint": "^9.32.0", "front-matter-plugin-api-provider": "^0.1.4-alpha", + "globals": "^16.3.0", + "jiti": "^2.5.1", "obsidian": "latest", "obsidian-typings": "^2.2.0", "tslib": "2.4.0", - "typescript": "4.7.4" + "typescript": "^4.8.4", + "typescript-eslint": "^8.38.0" } }, "node_modules/@codemirror/state": { @@ -76,42 +81,96 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "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" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "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/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -119,35 +178,98 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", - "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", "dev": true, - "peer": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, - "peer": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", + "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@eslint/core": "^0.15.1", + "levn": "^0.4.1" }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -155,7 +277,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "peer": true, "engines": { "node": ">=12.22" }, @@ -164,12 +285,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "peer": true + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -264,10 +392,11 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", @@ -277,10 +406,11 @@ "peer": true }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/keyv": { "version": "3.1.4", @@ -361,6 +491,55 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", + "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.29.0", + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/typescript-estree": "5.29.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/@typescript-eslint/parser": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", @@ -388,6 +567,42 @@ } } }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", + "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.38.0", + "@typescript-eslint/types": "^8.38.0", + "debug": "^4.3.4" + }, + "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/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", + "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/@typescript-eslint/scope-manager": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", @@ -405,6 +620,23 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", + "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", + "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/@typescript-eslint/type-utils": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", @@ -431,6 +663,55 @@ } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", + "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.29.0", + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/typescript-estree": "5.29.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/@typescript-eslint/types": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", @@ -471,30 +752,6 @@ } } }, - "node_modules/@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", @@ -513,11 +770,11 @@ } }, "node_modules/acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "peer": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -530,7 +787,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "peer": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -540,7 +797,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -552,22 +809,11 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "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, - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -583,7 +829,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "peer": true + "license": "Python-2.0" }, "node_modules/array-union": { "version": "2.1.0", @@ -599,7 +845,7 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/boolean": { "version": "3.2.0", @@ -610,11 +856,11 @@ "peer": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -625,6 +871,7 @@ "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" }, @@ -688,7 +935,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -698,7 +945,6 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -728,7 +974,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -740,22 +985,21 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -816,7 +1060,7 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/defer-to-connect": { "version": "2.0.1", @@ -886,19 +1130,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/electron": { "version": "31.4.0", "resolved": "https://registry.npmjs.org/electron/-/electron-31.4.0.tgz", @@ -1362,7 +1593,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -1371,73 +1601,81 @@ } }, "node_modules/eslint": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", - "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", + "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.43.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.32.0", + "@eslint/plugin-kit": "^0.3.4", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", + "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": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "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": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-utils": { @@ -1445,6 +1683,7 @@ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -1463,6 +1702,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10" } @@ -1479,46 +1719,45 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "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==", "dev": true, - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, - "peer": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1529,7 +1768,6 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, - "peer": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -1537,16 +1775,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -1559,20 +1787,12 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -1582,7 +1802,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "peer": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -1613,19 +1833,20 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "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.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -1648,14 +1869,14 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/fastq": { "version": "1.15.0", @@ -1677,16 +1898,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -1694,6 +1915,7 @@ "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" }, @@ -1706,7 +1928,6 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -1719,25 +1940,25 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, - "peer": true + "license": "ISC" }, "node_modules/front-matter-plugin-api-provider": { "version": "0.1.4-alpha", @@ -1763,13 +1984,6 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "peer": true - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1808,41 +2022,20 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "peer": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "peer": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "pump": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/glob-parent": { @@ -1850,7 +2043,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "peer": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -1878,16 +2070,13 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1983,14 +2172,13 @@ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -2082,11 +2270,11 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2103,29 +2291,10 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "peer": true, "engines": { "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "peer": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "peer": true - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2152,33 +2321,34 @@ "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-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, - "peer": true + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2190,22 +2360,20 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/json-stringify-safe": { "version": "5.0.1", @@ -2230,7 +2398,6 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "peer": true, "dependencies": { "json-buffer": "3.0.1" } @@ -2240,7 +2407,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -2254,7 +2421,6 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -2269,8 +2435,7 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/lowercase-keys": { "version": "2.0.0", @@ -2282,18 +2447,6 @@ "node": ">=8" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -2318,12 +2471,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "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.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -2345,7 +2499,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "peer": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2372,8 +2526,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/normalize-url": { "version": "6.1.0", @@ -2435,18 +2588,18 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -2467,7 +2620,6 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -2483,7 +2635,6 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -2499,7 +2650,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -2512,27 +2663,16 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "peer": true, "engines": { "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2558,6 +2698,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -2570,7 +2711,7 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -2597,11 +2738,11 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2663,7 +2804,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2691,22 +2832,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -2750,13 +2875,11 @@ } }, "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -2808,7 +2931,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -2821,7 +2944,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2843,25 +2966,12 @@ "optional": true, "peer": true }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -2881,110 +2991,360 @@ "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, - "peer": true, + "peer": true, + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typescript-eslint": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.38.0.tgz", + "integrity": "sha512-FsZlrYK6bPDGoLeZRuvx2v6qrM03I0U0SnfCLPs/XCCPCFD80xU9Pg09H/K+XFa68uJuZo7l/Xhs+eDRg2l3hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.38.0", + "@typescript-eslint/parser": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0" + }, + "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/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz", + "integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/type-utils": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.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-eslint/parser": "^8.38.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz", + "integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4" + }, + "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/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", + "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", + "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.0" + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0" }, "engines": { - "node": ">= 8.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", + "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=8" + "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/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", "dev": true, - "peer": 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/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==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", + "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "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": ">=8.0" + "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/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", + "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^1.8.1" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0" }, "engines": { - "node": ">= 6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", + "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "@typescript-eslint/types": "8.38.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">= 0.8.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/typescript-eslint/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "peer": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typescript-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==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "node_modules/typescript-eslint/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/typescript-eslint/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=4.2.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/undici-types": { @@ -3009,7 +3369,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "peer": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -3026,7 +3386,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "peer": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3042,7 +3402,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "peer": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3054,12 +3414,6 @@ "dev": true, "peer": true }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -3076,7 +3430,6 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -3132,72 +3485,136 @@ } }, "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, - "peer": true, "requires": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + } } }, "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true + }, + "@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, - "peer": true + "requires": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + } + }, + "@eslint/config-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "dev": true + }, + "@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.15" + } }, "@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, - "peer": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true + } } }, "@eslint/js": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", - "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "dev": true + }, + "@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true + }, + "@eslint/plugin-kit": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", + "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", "dev": true, - "peer": true + "requires": { + "@eslint/core": "^0.15.1", + "levn": "^0.4.1" + } + }, + "@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true }, - "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, - "peer": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "dependencies": { + "@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true + } } }, "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "peer": true + "dev": true }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true, - "peer": true + "@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -3270,9 +3687,9 @@ } }, "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true }, "@types/http-cache-semantics": { @@ -3283,9 +3700,9 @@ "peer": true }, "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "@types/keyv": { @@ -3349,6 +3766,38 @@ "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" + }, + "dependencies": { + "@typescript-eslint/utils": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", + "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.29.0", + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/typescript-estree": "5.29.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } } }, "@typescript-eslint/parser": { @@ -3363,6 +3812,25 @@ "debug": "^4.3.4" } }, + "@typescript-eslint/project-service": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", + "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", + "dev": true, + "requires": { + "@typescript-eslint/tsconfig-utils": "^8.38.0", + "@typescript-eslint/types": "^8.38.0", + "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", + "dev": true + } + } + }, "@typescript-eslint/scope-manager": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", @@ -3373,6 +3841,13 @@ "@typescript-eslint/visitor-keys": "5.29.0" } }, + "@typescript-eslint/tsconfig-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", + "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", + "dev": true, + "requires": {} + }, "@typescript-eslint/type-utils": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", @@ -3382,6 +3857,38 @@ "@typescript-eslint/utils": "5.29.0", "debug": "^4.3.4", "tsutils": "^3.21.0" + }, + "dependencies": { + "@typescript-eslint/utils": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", + "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.29.0", + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/typescript-estree": "5.29.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } } }, "@typescript-eslint/types": { @@ -3405,20 +3912,6 @@ "tsutils": "^3.21.0" } }, - "@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, "@typescript-eslint/visitor-keys": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", @@ -3430,18 +3923,16 @@ } }, "acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", - "dev": true, - "peer": true + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "peer": true, "requires": {} }, "ajv": { @@ -3449,7 +3940,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3457,19 +3947,11 @@ "uri-js": "^4.2.2" } }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "peer": true - }, "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, - "peer": true, "requires": { "color-convert": "^2.0.1" } @@ -3478,8 +3960,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "peer": true + "dev": true }, "array-union": { "version": "2.1.0", @@ -3491,8 +3972,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "peer": true + "dev": true }, "boolean": { "version": "3.2.0", @@ -3503,11 +3983,10 @@ "peer": true }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "peer": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3562,15 +4041,13 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "peer": true + "dev": true }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "peer": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3591,7 +4068,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "peer": true, "requires": { "color-name": "~1.1.4" } @@ -3600,22 +4076,19 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "peer": true + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "peer": true + "dev": true }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "peer": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3654,8 +4127,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "peer": true + "dev": true }, "defer-to-connect": { "version": "2.0.1", @@ -3701,20 +4173,10 @@ "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "peer": true, "requires": { - "esutils": "^2.0.2" + "path-type": "^4.0.0" } }, "electron": { @@ -3957,85 +4419,67 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "peer": true + "dev": true }, "eslint": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", - "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", + "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", "dev": true, - "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.43.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.32.0", + "@eslint/plugin-kit": "^0.3.4", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", + "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": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "dependencies": { - "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "dev": true, - "peer": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "peer": true + "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 } } }, "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "requires": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" } }, "eslint-utils": { @@ -4062,15 +4506,22 @@ "dev": true }, "espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, - "peer": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" + }, + "dependencies": { + "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 + } } }, "esquery": { @@ -4078,18 +4529,8 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, - "peer": true, "requires": { "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "peer": true - } } }, "esrecurse": { @@ -4099,28 +4540,19 @@ "dev": true, "requires": { "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "peer": true + "dev": true }, "extract-zip": { "version": "2.0.1", @@ -4139,20 +4571,19 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "peer": true + "dev": true }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "dependencies": { "glob-parent": { @@ -4170,15 +4601,13 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "peer": true + "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "peer": true + "dev": true }, "fastq": { "version": "1.15.0", @@ -4200,13 +4629,12 @@ } }, "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "peer": true, "requires": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" } }, "fill-range": { @@ -4223,29 +4651,26 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "peer": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "peer": true, "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" } }, "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true, - "peer": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true }, "front-matter-plugin-api-provider": { "version": "0.1.4-alpha", @@ -4268,13 +4693,6 @@ "universalify": "^0.1.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "peer": true - }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4314,27 +4732,11 @@ "pump": "^3.0.0" } }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "peer": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "peer": true, "requires": { "is-glob": "^4.0.3" } @@ -4356,14 +4758,10 @@ } }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "peer": true, - "requires": { - "type-fest": "^0.20.2" - } + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "dev": true }, "globalthis": { "version": "1.0.4", @@ -4433,15 +4831,13 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "peer": true + "dev": true }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "peer": true + "dev": true }, "has-property-descriptors": { "version": "1.0.2", @@ -4506,11 +4902,10 @@ "dev": true }, "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, - "peer": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -4520,26 +4915,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "peer": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "peer": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "peer": true + "dev": true }, "is-extglob": { "version": "2.1.1", @@ -4562,26 +4938,23 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "peer": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "peer": true + "dev": true + }, + "jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "dev": true }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "peer": true, "requires": { "argparse": "^2.0.1" } @@ -4590,22 +4963,19 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "peer": true + "dev": true }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "peer": true + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "peer": true + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -4630,7 +5000,6 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "peer": true, "requires": { "json-buffer": "3.0.1" } @@ -4640,7 +5009,6 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "peer": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -4651,7 +5019,6 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "peer": true, "requires": { "p-locate": "^5.0.0" } @@ -4660,8 +5027,7 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "peer": true + "dev": true }, "lowercase-keys": { "version": "2.0.0", @@ -4670,15 +5036,6 @@ "dev": true, "peer": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -4697,12 +5054,12 @@ "dev": true }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, @@ -4718,7 +5075,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "peer": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4739,8 +5095,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "peer": true + "dev": true }, "normalize-url": { "version": "6.1.0", @@ -4785,18 +5140,17 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "peer": true, "requires": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" } }, "p-cancelable": { @@ -4811,7 +5165,6 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "peer": true, "requires": { "yocto-queue": "^0.1.0" } @@ -4821,7 +5174,6 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "peer": true, "requires": { "p-limit": "^3.0.2" } @@ -4831,7 +5183,6 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "peer": true, "requires": { "callsites": "^3.0.0" } @@ -4840,22 +5191,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "peer": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "peer": true + "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "peer": true + "dev": true }, "path-type": { "version": "4.0.0", @@ -4880,8 +5222,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "peer": true + "dev": true }, "progress": { "version": "2.0.3", @@ -4902,11 +5243,10 @@ } }, "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "peer": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true }, "queue-microtask": { "version": "1.2.3", @@ -4938,8 +5278,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "peer": true + "dev": true }, "responselike": { "version": "2.0.1", @@ -4957,16 +5296,6 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "peer": true, - "requires": { - "glob": "^7.1.3" - } - }, "roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -4993,13 +5322,10 @@ } }, "semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true }, "semver-compare": { "version": "1.0.0", @@ -5035,7 +5361,6 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "peer": true, "requires": { "shebang-regex": "^3.0.0" } @@ -5044,8 +5369,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "peer": true + "dev": true }, "slash": { "version": "3.0.0", @@ -5061,22 +5385,11 @@ "optional": true, "peer": true }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "peer": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "peer": true + "dev": true }, "style-mod": { "version": "4.0.3", @@ -5100,18 +5413,10 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "peer": true, "requires": { "has-flag": "^4.0.0" } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "peer": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5121,6 +5426,13 @@ "is-number": "^7.0.0" } }, + "ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "requires": {} + }, "tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -5149,24 +5461,159 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "peer": true, "requires": { "prelude-ls": "^1.2.1" } }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "peer": true - }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, + "typescript-eslint": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.38.0.tgz", + "integrity": "sha512-FsZlrYK6bPDGoLeZRuvx2v6qrM03I0U0SnfCLPs/XCCPCFD80xU9Pg09H/K+XFa68uJuZo7l/Xhs+eDRg2l3hg==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "8.38.0", + "@typescript-eslint/parser": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0" + }, + "dependencies": { + "@typescript-eslint/eslint-plugin": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz", + "integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/type-utils": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + } + }, + "@typescript-eslint/parser": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz", + "integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", + "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", + "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + } + }, + "@typescript-eslint/types": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", + "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", + "dev": true, + "requires": { + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "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" + } + }, + "@typescript-eslint/utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", + "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", + "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.38.0", + "eslint-visitor-keys": "^4.2.1" + } + }, + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "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 + }, + "ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -5186,7 +5633,6 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "peer": true, "requires": { "punycode": "^2.1.0" } @@ -5203,7 +5649,6 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "peer": true, "requires": { "isexe": "^2.0.0" } @@ -5212,8 +5657,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "peer": true + "dev": true }, "wrappy": { "version": "1.0.2", @@ -5222,12 +5666,6 @@ "dev": true, "peer": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -5243,8 +5681,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "peer": true + "dev": true } } } diff --git a/package.json b/package.json index 8cd6454..f459e2a 100644 --- a/package.json +++ b/package.json @@ -16,16 +16,21 @@ "author": "Lost Paul", "license": "GPL-3.0-or-later", "devDependencies": { + "@eslint/js": "^9.32.0", "@types/node": "^16.11.6", "@typescript-eslint/eslint-plugin": "5.29.0", "@typescript-eslint/parser": "5.29.0", "builtin-modules": "3.3.0", "esbuild": "0.14.47", + "eslint": "^9.32.0", "front-matter-plugin-api-provider": "^0.1.4-alpha", + "globals": "^16.3.0", + "jiti": "^2.5.1", "obsidian": "latest", "obsidian-typings": "^2.2.0", "tslib": "2.4.0", - "typescript": "4.7.4" + "typescript": "^4.8.4", + "typescript-eslint": "^8.38.0" }, "dependencies": { "@popperjs/core": "^2.11.6" diff --git a/src/Commands.ts b/src/Commands.ts index 8e304e7..56f7dd1 100644 --- a/src/Commands.ts +++ b/src/Commands.ts @@ -1,5 +1,6 @@ -import { App, TFolder, Menu, TAbstractFile, Notice, TFile, Editor, MarkdownView, Platform } from 'obsidian'; -import FolderNotesPlugin from './main'; +import type { App, Menu, TAbstractFile, Editor, MarkdownView } from 'obsidian'; +import { TFolder, Notice, TFile, Platform } from 'obsidian'; +import type FolderNotesPlugin from './main'; import { getFolderNote, createFolderNote, deleteFolderNote, turnIntoFolderNote, openFolderNote, extractFolderName, detachFolderNote } from './functions/folderNoteFunctions'; import { ExcludedFolder } from './ExcludeFolders/ExcludeFolder'; import { getFolderPathFromString, getFileExplorerActiveFolder } from './functions/utils'; @@ -108,7 +109,7 @@ export class Commands { // Everything is fine and not checking, let's create the folder note. const ext = '.' + fileType; - const path = folder.path; + const { path } = folder; createFolderNote(this.plugin, path, true, ext, false); }, }); @@ -179,7 +180,7 @@ export class Commands { name: 'Create folder note from selection', editorCheckCallback: (checking: boolean, editor: Editor, view: MarkdownView) => { const text = editor.getSelection().trim(); - const file = view.file; + const { file } = view; if (!(file instanceof TFile)) return false; if (text && text.trim() !== '') { if (checking) { return true; } @@ -201,10 +202,10 @@ export class Commands { if (folder instanceof TFolder) { new Notice('Folder note already exists'); return false; - } else { - this.plugin.app.vault.createFolder(text); - createFolderNote(this.plugin, text, false); } + this.plugin.app.vault.createFolder(text); + createFolderNote(this.plugin, text, false); + } else { folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + '/' + text); if (folder instanceof TFolder) { @@ -447,7 +448,7 @@ export class Commands { item.setTitle('Create folder note') .setIcon('edit') .onClick(() => { - const file = view.file; + const { file } = view; if (!(file instanceof TFile)) return; const blacklist = ['*', '\\', '"', '/', '<', '>', '?', '|', ':']; for (const char of blacklist) { @@ -467,10 +468,10 @@ export class Commands { folder = this.plugin.app.vault.getAbstractFileByPath(text); if (folder instanceof TFolder) { return new Notice('Folder note already exists'); - } else { - this.plugin.app.vault.createFolder(text); - createFolderNote(this.plugin, text, false); } + this.plugin.app.vault.createFolder(text); + createFolderNote(this.plugin, text, false); + } else { folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + '/' + text); if (folder instanceof TFolder) { diff --git a/src/ExcludeFolders/ExcludeFolder.ts b/src/ExcludeFolders/ExcludeFolder.ts index 8eda370..24af3ab 100644 --- a/src/ExcludeFolders/ExcludeFolder.ts +++ b/src/ExcludeFolders/ExcludeFolder.ts @@ -1,4 +1,4 @@ -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; export class ExcludedFolder { type: string; id: string; diff --git a/src/ExcludeFolders/ExcludePattern.ts b/src/ExcludeFolders/ExcludePattern.ts index 6839069..c78aab3 100644 --- a/src/ExcludeFolders/ExcludePattern.ts +++ b/src/ExcludeFolders/ExcludePattern.ts @@ -1,4 +1,4 @@ -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; export class ExcludePattern { type: string; id: string; diff --git a/src/ExcludeFolders/WhitelistFolder.ts b/src/ExcludeFolders/WhitelistFolder.ts index f0b40db..e290926 100644 --- a/src/ExcludeFolders/WhitelistFolder.ts +++ b/src/ExcludeFolders/WhitelistFolder.ts @@ -1,4 +1,4 @@ -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; export class WhitelistedFolder { type: string; id: string; diff --git a/src/ExcludeFolders/WhitelistPattern.ts b/src/ExcludeFolders/WhitelistPattern.ts index 43ecd45..bf9fe91 100644 --- a/src/ExcludeFolders/WhitelistPattern.ts +++ b/src/ExcludeFolders/WhitelistPattern.ts @@ -1,4 +1,4 @@ -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; export class WhitelistedPattern { type: string; id: string; diff --git a/src/ExcludeFolders/functions/folderFunctions.ts b/src/ExcludeFolders/functions/folderFunctions.ts index 1c48af0..a2fb61c 100644 --- a/src/ExcludeFolders/functions/folderFunctions.ts +++ b/src/ExcludeFolders/functions/folderFunctions.ts @@ -1,15 +1,15 @@ -import FolderNotesPlugin from '../../main'; +import type FolderNotesPlugin from '../../main'; import { getFolderNameFromPathString, getFolderPathFromString } from '../../functions/utils'; -import { ExcludedFolder } from '../ExcludeFolder'; +import type { ExcludedFolder } from '../ExcludeFolder'; import { ExcludePattern } from '../ExcludePattern'; import { Platform, Setting } from 'obsidian'; import { FolderSuggest } from '../../suggesters/FolderSuggester'; -import { SettingsTab } from '../../settings/SettingsTab'; +import type { SettingsTab } from '../../settings/SettingsTab'; import ExcludedFolderSettings from '../modals/ExcludeFolderSettings'; import { updatePattern, getExcludedFoldersByPattern, addExcludePatternListItem } from './patternFunctions'; import { getWhitelistedFolder } from './whitelistFolderFunctions'; -import { WhitelistedFolder } from '../WhitelistFolder'; -import { WhitelistedPattern } from '../WhitelistPattern'; +import type { WhitelistedFolder } from '../WhitelistFolder'; +import type { WhitelistedPattern } from '../WhitelistPattern'; export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, includeDetached: boolean, pathOnly?: boolean, ignoreWhitelist?: boolean) { let excludedFolder = {} as ExcludedFolder | ExcludePattern | undefined; @@ -97,9 +97,9 @@ export function getExcludedFolderByPath(plugin: FolderNotesPlugin, path: string) if (folderPath.includes('/') || folderPath.includes('\\')) { return folderPath.startsWith(excludedFolderPath) || folderPath === excludedFolderPath; - } else { - return folderPath === excludedFolderPath; } + return folderPath === excludedFolderPath; + }); } @@ -114,9 +114,9 @@ export function getExcludedFoldersByPath(plugin: FolderNotesPlugin, path: string if (folderPath.includes('/') || folderPath.includes('\\')) { return folderPath.startsWith(excludedFolderPath) || folderPath === excludedFolderPath; - } else { - return folderPath === excludedFolderPath; } + return folderPath === excludedFolderPath; + }); } @@ -146,14 +146,14 @@ export function resyncArray(plugin: FolderNotesPlugin) { export function addExcludeFolderListItem(settings: SettingsTab, containerEl: HTMLElement, excludedFolder: ExcludedFolder) { - const plugin: FolderNotesPlugin = settings.plugin; + const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); setting.addSearch((cb) => { new FolderSuggest( cb.inputEl, plugin, - false + false, ); // @ts-ignore cb.containerEl.addClass('fn-exclude-folder-path'); diff --git a/src/ExcludeFolders/functions/patternFunctions.ts b/src/ExcludeFolders/functions/patternFunctions.ts index c3f8c8b..8e4e4ae 100644 --- a/src/ExcludeFolders/functions/patternFunctions.ts +++ b/src/ExcludeFolders/functions/patternFunctions.ts @@ -1,7 +1,7 @@ -import FolderNotesPlugin from '../../main'; -import { ExcludePattern } from '../ExcludePattern'; +import type FolderNotesPlugin from '../../main'; +import type { ExcludePattern } from '../ExcludePattern'; import { Setting, Platform } from 'obsidian'; -import { SettingsTab } from '../../settings/SettingsTab'; +import type { SettingsTab } from '../../settings/SettingsTab'; import { addExcludedFolder, resyncArray, updateExcludedFolder } from './folderFunctions'; import PatternSettings from '../modals/PatternSettings'; @@ -73,7 +73,7 @@ export function getExcludedFolderByPattern(plugin: FolderNotesPlugin, folderName } export function addExcludePatternListItem(settings: SettingsTab, containerEl: HTMLElement, pattern: ExcludePattern) { - const plugin: FolderNotesPlugin = settings.plugin; + const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); setting.addSearch((cb) => { diff --git a/src/ExcludeFolders/functions/whitelistFolderFunctions.ts b/src/ExcludeFolders/functions/whitelistFolderFunctions.ts index 78cdba1..156a716 100644 --- a/src/ExcludeFolders/functions/whitelistFolderFunctions.ts +++ b/src/ExcludeFolders/functions/whitelistFolderFunctions.ts @@ -1,10 +1,10 @@ -import FolderNotesPlugin from '../../main'; +import type FolderNotesPlugin from '../../main'; import { getFolderNameFromPathString, getFolderPathFromString } from '../../functions/utils'; -import { WhitelistedFolder } from '../WhitelistFolder'; +import type { WhitelistedFolder } from '../WhitelistFolder'; import { WhitelistedPattern } from '../WhitelistPattern'; import { Setting, Platform, ButtonComponent } from 'obsidian'; import { FolderSuggest } from '../../suggesters/FolderSuggester'; -import { SettingsTab } from '../../settings/SettingsTab'; +import type { SettingsTab } from '../../settings/SettingsTab'; import WhitelistFolderSettings from '../modals/WhitelistFolderSettings'; import { updateWhitelistedPattern, getWhitelistedFoldersByPattern, addWhitelistedPatternListItem } from './whitelistPatternFunctions'; Platform.isMobileApp; @@ -81,7 +81,7 @@ export function resyncArray(plugin: FolderNotesPlugin) { export function addWhitelistFolderListItem(settings: SettingsTab, containerEl: HTMLElement, whitelistedFolder: WhitelistedFolder) { - const plugin: FolderNotesPlugin = settings.plugin; + const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); @@ -91,7 +91,7 @@ export function addWhitelistFolderListItem(settings: SettingsTab, containerEl: H new FolderSuggest( cb.inputEl, plugin, - true + true, ); // @ts-ignore cb.containerEl.addClass('fn-exclude-folder-path'); diff --git a/src/ExcludeFolders/functions/whitelistPatternFunctions.ts b/src/ExcludeFolders/functions/whitelistPatternFunctions.ts index 6253e8c..30f5363 100644 --- a/src/ExcludeFolders/functions/whitelistPatternFunctions.ts +++ b/src/ExcludeFolders/functions/whitelistPatternFunctions.ts @@ -1,9 +1,9 @@ -import FolderNotesPlugin from '../../main'; +import type FolderNotesPlugin from '../../main'; import { Setting } from 'obsidian'; -import { SettingsTab } from '../../settings/SettingsTab'; +import type { SettingsTab } from '../../settings/SettingsTab'; import { resyncArray } from './folderFunctions'; import WhitelistPatternSettings from '../modals/WhitelistPatternSettings'; -import { WhitelistedPattern } from '../WhitelistPattern'; +import type { WhitelistedPattern } from '../WhitelistPattern'; import { addWhitelistedFolder, updateWhitelistedFolder } from './whitelistFolderFunctions'; export function updateWhitelistedPattern(plugin: FolderNotesPlugin, pattern: WhitelistedPattern, newPattern: WhitelistedPattern) { @@ -74,7 +74,7 @@ export function getWhitelistedFoldersByPattern(plugin: FolderNotesPlugin, folder } export function addWhitelistedPatternListItem(settings: SettingsTab, containerEl: HTMLElement, pattern: WhitelistedPattern) { - const plugin: FolderNotesPlugin = settings.plugin; + const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); setting.addSearch((cb) => { diff --git a/src/ExcludeFolders/modals/ExcludeFolderSettings.ts b/src/ExcludeFolders/modals/ExcludeFolderSettings.ts index 7326bc6..7f634b2 100644 --- a/src/ExcludeFolders/modals/ExcludeFolderSettings.ts +++ b/src/ExcludeFolders/modals/ExcludeFolderSettings.ts @@ -1,6 +1,7 @@ -import { App, Modal, Setting } from 'obsidian'; -import FolderNotesPlugin from '../../main'; -import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; +import type { App } from 'obsidian'; +import { Modal, Setting } from 'obsidian'; +import type FolderNotesPlugin from '../../main'; +import type { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; import { updateCSSClassesForFolder } from 'src/functions/styleFunctions'; export default class ExcludedFolderSettings extends Modal { plugin: FolderNotesPlugin; @@ -28,7 +29,7 @@ export default class ExcludedFolderSettings extends Modal { .onChange(async (value) => { this.excludedFolder.subFolders = value; await this.plugin.saveSettings(true); - }) + }), ); new Setting(contentEl) @@ -40,7 +41,7 @@ export default class ExcludedFolderSettings extends Modal { .onChange(async (value) => { this.excludedFolder.disableSync = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -52,7 +53,7 @@ export default class ExcludedFolderSettings extends Modal { .onChange(async (value) => { this.excludedFolder.excludeFromFolderOverview = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -66,7 +67,7 @@ export default class ExcludedFolderSettings extends Modal { updateCSSClassesForFolder(this.excludedFolder.path, this.plugin); await this.plugin.saveSettings(); this.display(); - }) + }), ); new Setting(contentEl) @@ -78,7 +79,7 @@ export default class ExcludedFolderSettings extends Modal { .onChange(async (value) => { this.excludedFolder.disableAutoCreate = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -91,7 +92,7 @@ export default class ExcludedFolderSettings extends Modal { this.excludedFolder.disableFolderNote = value; await this.plugin.saveSettings(true); this.display(); - }) + }), ); if (!this.excludedFolder.disableFolderNote) { @@ -104,7 +105,7 @@ export default class ExcludedFolderSettings extends Modal { .onChange(async (value) => { this.excludedFolder.enableCollapsing = value; await this.plugin.saveSettings(); - }) + }), ); } diff --git a/src/ExcludeFolders/modals/PatternSettings.ts b/src/ExcludeFolders/modals/PatternSettings.ts index a353c26..426f228 100644 --- a/src/ExcludeFolders/modals/PatternSettings.ts +++ b/src/ExcludeFolders/modals/PatternSettings.ts @@ -1,6 +1,7 @@ -import { App, Modal, Setting } from 'obsidian'; -import FolderNotesPlugin from '../../main'; -import { ExcludePattern } from 'src/ExcludeFolders/ExcludePattern'; +import type { App } from 'obsidian'; +import { Modal, Setting } from 'obsidian'; +import type FolderNotesPlugin from '../../main'; +import type { ExcludePattern } from 'src/ExcludeFolders/ExcludePattern'; import { refreshAllFolderStyles } from 'src/functions/styleFunctions'; export default class PatternSettings extends Modal { @@ -30,7 +31,7 @@ export default class PatternSettings extends Modal { .onChange(async (value) => { this.pattern.disableSync = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -42,7 +43,7 @@ export default class PatternSettings extends Modal { .onChange(async (value) => { this.pattern.disableAutoCreate = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -54,7 +55,7 @@ export default class PatternSettings extends Modal { .onChange(async (value) => { this.pattern.excludeFromFolderOverview = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -68,7 +69,7 @@ export default class PatternSettings extends Modal { await this.plugin.saveSettings(); refreshAllFolderStyles(true, this.plugin); this.display(); - }) + }), ); new Setting(contentEl) @@ -81,7 +82,7 @@ export default class PatternSettings extends Modal { this.pattern.disableFolderNote = value; await this.plugin.saveSettings(true); this.display(); - }) + }), ); if (!this.pattern.disableFolderNote) { @@ -94,7 +95,7 @@ export default class PatternSettings extends Modal { .onChange(async (value) => { this.pattern.enableCollapsing = value; await this.plugin.saveSettings(); - }) + }), ); } diff --git a/src/ExcludeFolders/modals/WhitelistFolderSettings.ts b/src/ExcludeFolders/modals/WhitelistFolderSettings.ts index 9673758..6f65cc7 100644 --- a/src/ExcludeFolders/modals/WhitelistFolderSettings.ts +++ b/src/ExcludeFolders/modals/WhitelistFolderSettings.ts @@ -1,6 +1,7 @@ -import { App, Modal, Setting } from 'obsidian'; -import FolderNotesPlugin from '../../main'; -import { WhitelistedFolder } from '../WhitelistFolder'; +import type { App } from 'obsidian'; +import { Modal, Setting } from 'obsidian'; +import type FolderNotesPlugin from '../../main'; +import type { WhitelistedFolder } from '../WhitelistFolder'; export default class WhitelistFolderSettings extends Modal { plugin: FolderNotesPlugin; app: App; @@ -27,7 +28,7 @@ export default class WhitelistFolderSettings extends Modal { .onChange(async (value) => { this.whitelistedFolder.subFolders = value; await this.plugin.saveSettings(true); - }) + }), ); new Setting(contentEl) @@ -39,7 +40,7 @@ export default class WhitelistFolderSettings extends Modal { .onChange(async (value) => { this.whitelistedFolder.enableSync = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -51,7 +52,7 @@ export default class WhitelistFolderSettings extends Modal { .onChange(async (value) => { this.whitelistedFolder.showInFolderOverview = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -63,7 +64,7 @@ export default class WhitelistFolderSettings extends Modal { .onChange(async (value) => { this.whitelistedFolder.hideInFileExplorer = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -74,7 +75,7 @@ export default class WhitelistFolderSettings extends Modal { .onChange(async (value) => { this.whitelistedFolder.enableAutoCreate = value; await this.plugin.saveSettings(); - }) + }), ); @@ -88,7 +89,7 @@ export default class WhitelistFolderSettings extends Modal { this.whitelistedFolder.enableFolderNote = value; await this.plugin.saveSettings(true); this.display(); - }) + }), ); if (this.whitelistedFolder.enableFolderNote) { @@ -101,7 +102,7 @@ export default class WhitelistFolderSettings extends Modal { .onChange(async (value) => { this.whitelistedFolder.disableCollapsing = value; await this.plugin.saveSettings(); - }) + }), ); } diff --git a/src/ExcludeFolders/modals/WhitelistPatternSettings.ts b/src/ExcludeFolders/modals/WhitelistPatternSettings.ts index b328f34..45a3688 100644 --- a/src/ExcludeFolders/modals/WhitelistPatternSettings.ts +++ b/src/ExcludeFolders/modals/WhitelistPatternSettings.ts @@ -1,6 +1,7 @@ -import { App, Modal, Setting } from 'obsidian'; -import FolderNotesPlugin from '../../main'; -import { WhitelistedPattern } from '../WhitelistPattern'; +import type { App } from 'obsidian'; +import { Modal, Setting } from 'obsidian'; +import type FolderNotesPlugin from '../../main'; +import type { WhitelistedPattern } from '../WhitelistPattern'; export default class WhitelistPatternSettings extends Modal { plugin: FolderNotesPlugin; @@ -28,7 +29,7 @@ export default class WhitelistPatternSettings extends Modal { .onChange(async (value) => { this.pattern.enableSync = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -39,7 +40,7 @@ export default class WhitelistPatternSettings extends Modal { .onChange(async (value) => { this.pattern.enableAutoCreate = value; await this.plugin.saveSettings(); - }) + }), ); new Setting(contentEl) @@ -51,7 +52,7 @@ export default class WhitelistPatternSettings extends Modal { .onChange(async (value) => { this.pattern.showInFolderOverview = value; await this.plugin.saveSettings(); - }) + }), ); @@ -65,7 +66,7 @@ export default class WhitelistPatternSettings extends Modal { this.pattern.enableFolderNote = value; await this.plugin.saveSettings(true); this.display(); - }) + }), ); if (this.pattern.enableFolderNote) { @@ -78,7 +79,7 @@ export default class WhitelistPatternSettings extends Modal { .onChange(async (value) => { this.pattern.disableCollapsing = value; await this.plugin.saveSettings(); - }) + }), ); } diff --git a/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts b/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts index 3208d57..2321f34 100644 --- a/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts +++ b/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts @@ -1,6 +1,7 @@ -import { App, Modal, Setting } from 'obsidian'; -import { SettingsTab } from 'src/settings/SettingsTab'; -import FolderNotesPlugin from '../../main'; +import type { App } from 'obsidian'; +import { Modal, Setting } from 'obsidian'; +import type { SettingsTab } from 'src/settings/SettingsTab'; +import type FolderNotesPlugin from '../../main'; import { WhitelistedFolder } from '../WhitelistFolder'; import { addWhitelistFolderListItem, addWhitelistedFolder } from '../functions/whitelistFolderFunctions'; import { addWhitelistedPatternListItem } from '../functions/whitelistPatternFunctions'; diff --git a/src/events/FrontMatterTitle.ts b/src/events/FrontMatterTitle.ts index 224faf6..3586346 100644 --- a/src/events/FrontMatterTitle.ts +++ b/src/events/FrontMatterTitle.ts @@ -1,6 +1,8 @@ -import FolderNotesPlugin from 'src/main'; -import { getDefer, Listener, Events, ApiInterface, DeferInterface, ListenerRef, EventDispatcherInterface } from 'front-matter-plugin-api-provider'; -import { App, TFile, TFolder } from 'obsidian'; +import type FolderNotesPlugin from 'src/main'; +import type { Listener, Events, ApiInterface, DeferInterface, ListenerRef, EventDispatcherInterface } from 'front-matter-plugin-api-provider'; +import { getDefer } from 'front-matter-plugin-api-provider'; +import type { App } from 'obsidian'; +import { TFile, TFolder } from 'obsidian'; import { getFolder, getFolderNote } from 'src/functions/folderNoteFunctions'; export class FrontMatterTitlePluginHandler { plugin: FolderNotesPlugin; @@ -77,7 +79,7 @@ export class FrontMatterTitlePluginHandler { this.plugin.changeFolderNameInExplorer(folder, newName); } - const breadcrumb = data.breadcrumb; + const { breadcrumb } = data; if (breadcrumb) { this.plugin.changeFolderNameInPath(folder, newName, breadcrumb); } @@ -117,7 +119,7 @@ export class FrontMatterTitlePluginHandler { this.plugin.changeFolderNameInExplorer(folder, newName); } - const breadcrumb = data.breadcrumb; + const { breadcrumb } = data; if (breadcrumb) { this.plugin.changeFolderNameInPath(folder, newName, breadcrumb); } diff --git a/src/events/MutationObserver.ts b/src/events/MutationObserver.ts index f4b5295..a03a5e0 100644 --- a/src/events/MutationObserver.ts +++ b/src/events/MutationObserver.ts @@ -1,5 +1,5 @@ import { Keymap, Platform } from 'obsidian'; -import FolderNotesPlugin from 'src/main'; +import type FolderNotesPlugin from 'src/main'; import { getFolderNote } from 'src/functions/folderNoteFunctions'; import { handleViewHeaderClick } from './handleClick'; import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; @@ -26,7 +26,7 @@ export function registerFileExplorerObserver(plugin: FolderNotesPlugin) { if (!(titleContainer instanceof HTMLElement)) return; updateFolderNamesInPath(plugin, titleContainer); - }) + }), ); } diff --git a/src/events/TabManager.ts b/src/events/TabManager.ts index 131f7f8..11903ff 100644 --- a/src/events/TabManager.ts +++ b/src/events/TabManager.ts @@ -1,5 +1,6 @@ -import FolderNotesPlugin from 'src/main'; -import { App, EditableFileView, TFolder } from 'obsidian'; +import type FolderNotesPlugin from 'src/main'; +import type { App } from 'obsidian'; +import { EditableFileView, TFolder } from 'obsidian'; import { getFolder, getFolderNote } from 'src/functions/folderNoteFunctions'; export class TabManager { plugin: FolderNotesPlugin; diff --git a/src/events/handleClick.ts b/src/events/handleClick.ts index 4b3035a..fb8dc6f 100644 --- a/src/events/handleClick.ts +++ b/src/events/handleClick.ts @@ -1,5 +1,5 @@ import { Keymap, Platform } from 'obsidian'; -import FolderNotesPlugin from 'src/main'; +import type FolderNotesPlugin from 'src/main'; import { openFolderNote, createFolderNote, getFolderNote } from 'src/functions/folderNoteFunctions'; import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; import { addCSSClassToFileExplorerEl, removeCSSClassFromFileExplorerEL } from 'src/functions/styleFunctions'; diff --git a/src/events/handleCreate.ts b/src/events/handleCreate.ts index 0cbcaee..f65d3ed 100644 --- a/src/events/handleCreate.ts +++ b/src/events/handleCreate.ts @@ -1,5 +1,6 @@ -import { TAbstractFile, TFolder, TFile } from 'obsidian'; -import FolderNotesPlugin from 'src/main'; +import type { TAbstractFile } from 'obsidian'; +import { TFolder, TFile } from 'obsidian'; +import type FolderNotesPlugin from 'src/main'; import { createFolderNote, getFolder, getFolderNote, turnIntoFolderNote } from 'src/functions/folderNoteFunctions'; import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; import { removeCSSClassFromFileExplorerEL, addCSSClassToFileExplorerEl } from 'src/functions/styleFunctions'; diff --git a/src/events/handleDelete.ts b/src/events/handleDelete.ts index b2b644c..089c1ff 100644 --- a/src/events/handleDelete.ts +++ b/src/events/handleDelete.ts @@ -1,5 +1,6 @@ -import { TAbstractFile, TFolder, TFile } from 'obsidian'; -import FolderNotesPlugin from 'src/main'; +import type { TAbstractFile } from 'obsidian'; +import { TFolder, TFile } from 'obsidian'; +import type FolderNotesPlugin from 'src/main'; import { getFolderNote, getFolder, deleteFolderNote } from 'src/functions/folderNoteFunctions'; import { removeCSSClassFromFileExplorerEL, addCSSClassToFileExplorerEl, hideFolderNoteInFileExplorer } from 'src/functions/styleFunctions'; import { getFolderPathFromString } from 'src/functions/utils'; diff --git a/src/events/handleRename.ts b/src/events/handleRename.ts index 59c79b9..7ca75b2 100644 --- a/src/events/handleRename.ts +++ b/src/events/handleRename.ts @@ -1,5 +1,6 @@ -import { TFile, TFolder, TAbstractFile, Notice } from 'obsidian'; -import FolderNotesPlugin from 'src/main'; +import type { TAbstractFile } from 'obsidian'; +import { TFile, TFolder, Notice } from 'obsidian'; +import type FolderNotesPlugin from 'src/main'; import { extractFolderName, getFolderNote, getFolderNoteFolder } from '../functions/folderNoteFunctions'; import { getExcludedFolder, addExcludedFolder, updateExcludedFolder, deleteExcludedFolder, getDetachedFolder } from '../ExcludeFolders/functions/folderFunctions'; import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; @@ -32,15 +33,15 @@ export function handleRename(file: TAbstractFile, oldPath: string, plugin: Folde updateExcludedFolderPath(folder, oldPath, plugin); if (isFolderRename(folder, oldPath)) { return handleFolderRename(folder, oldPath, plugin); - } else { - return handleFolderMove(folder, oldPath, plugin); } + return handleFolderMove(folder, oldPath, plugin); + } else if (file instanceof TFile) { if (isFileRename(file, oldPath)) { return fmptUpdateFileName(file, oldPath, plugin); - } else { - return handleFileMove(file, oldPath, plugin); } + return handleFileMove(file, oldPath, plugin); + } } @@ -262,7 +263,7 @@ async function renameFolderOnFileRename(file: TFile, oldPath: string, oldFolder: function updateExcludedFolderPath(folder: TFolder, oldPath: string, plugin: FolderNotesPlugin) { const excludedFolders = plugin.settings.excludeFolders.filter( - (excludedFolder) => excludedFolder.path?.includes(oldPath) + (excludedFolder) => excludedFolder.path?.includes(oldPath), ); excludedFolders.forEach((excludedFolder) => { diff --git a/src/functions/excalidraw.ts b/src/functions/excalidraw.ts index c07baca..81eb8c8 100644 --- a/src/functions/excalidraw.ts +++ b/src/functions/excalidraw.ts @@ -1,4 +1,4 @@ -import { WorkspaceLeaf, App } from 'obsidian'; +import type { WorkspaceLeaf, App } from 'obsidian'; export async function openExcalidrawView(leaf: WorkspaceLeaf) { const { excalidraw, excalidrawEnabled } = await getExcalidrawPlugin(this.app); @@ -10,7 +10,7 @@ export async function openExcalidrawView(leaf: WorkspaceLeaf) { export async function getExcalidrawPlugin(app: App) { const excalidraw = (app as any).plugins.plugins['obsidian-excalidraw-plugin']; const excalidrawEnabled = (app as any).plugins.enabledPlugins.has( - 'obsidian-excalidraw-plugin' + 'obsidian-excalidraw-plugin', ); return { excalidraw, diff --git a/src/functions/folderNoteFunctions.ts b/src/functions/folderNoteFunctions.ts index 7eb78d7..17f6944 100644 --- a/src/functions/folderNoteFunctions.ts +++ b/src/functions/folderNoteFunctions.ts @@ -1,7 +1,8 @@ -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; import ExistingFolderNoteModal from '../modals/ExistingNote'; import { applyTemplate } from '../template'; -import { TFolder, TFile, TAbstractFile, Keymap } from 'obsidian'; +import type { TAbstractFile } from 'obsidian'; +import { TFolder, TFile, Keymap } from 'obsidian'; import DeleteConfirmationModal from '../modals/DeleteConfirmation'; import { addExcludedFolder, deleteExcludedFolder, getDetachedFolder, getExcludedFolder, updateExcludedFolder } from '../ExcludeFolders/functions/folderFunctions'; import { ExcludedFolder } from '../ExcludeFolders/ExcludeFolder'; @@ -146,7 +147,7 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st } export async function turnIntoFolderNote(plugin: FolderNotesPlugin, file: TFile, folder: TFolder, folderNote?: TFile | null | TAbstractFile, skipConfirmation?: boolean) { - const extension = file.extension; + const { extension } = file; const detachedExcludedFolder = getDetachedFolder(plugin, folder.path); if (folderNote) { @@ -214,7 +215,7 @@ export async function tempDisableSync(plugin: FolderNotesPlugin, folder: TFolder } export async function openFolderNote(plugin: FolderNotesPlugin, file: TAbstractFile, evt?: MouseEvent) { - const path = file.path; + const { path } = file; const focusExistingTab = plugin.settings.focusExistingTab && plugin.settings.openInNewTab; const activeFilePath = plugin.app.workspace.getActiveFile()?.path; @@ -310,7 +311,7 @@ export function getFolderNote(plugin: FolderNotesPlugin, folderPath: string, sto folder.path === '/' ? path = fileName : path = `${folder.path}/${fileName}`; - let folderNoteType = plugin.settings.folderNoteType; + let { folderNoteType } = plugin.settings; if (folderNoteType === '.excalidraw') { folderNoteType = '.md'; } @@ -318,21 +319,21 @@ export function getFolderNote(plugin: FolderNotesPlugin, folderPath: string, sto let folderNote = plugin.app.vault.getAbstractFileByPath(path + folderNoteType); if (folderNote instanceof TFile && plugin.settings.supportedFileTypes.includes(plugin.settings.folderNoteType.replace('.', ''))) { return folderNote; - } else { - const supportedFileTypes = plugin.settings.supportedFileTypes.filter((type) => type !== plugin.settings.folderNoteType.replace('.', '')); - for (let type of supportedFileTypes) { - if (type === 'excalidraw' || type === '.excalidraw') { - type = '.md'; - } - if (!type.startsWith('.')) { - type = '.' + type; - } - folderNote = plugin.app.vault.getAbstractFileByPath(path + type); - if (folderNote instanceof TFile) { - return folderNote; - } + } + const supportedFileTypes = plugin.settings.supportedFileTypes.filter((type) => type !== plugin.settings.folderNoteType.replace('.', '')); + for (let type of supportedFileTypes) { + if (type === 'excalidraw' || type === '.excalidraw') { + type = '.md'; + } + if (!type.startsWith('.')) { + type = '.' + type; + } + folderNote = plugin.app.vault.getAbstractFileByPath(path + type); + if (folderNote instanceof TFile) { + return folderNote; } } + } export function detachFolderNote(plugin: FolderNotesPlugin, file: TFile) { diff --git a/src/functions/styleFunctions.ts b/src/functions/styleFunctions.ts index 9965d35..d65d886 100644 --- a/src/functions/styleFunctions.ts +++ b/src/functions/styleFunctions.ts @@ -1,10 +1,10 @@ import { TFile, TFolder } from 'obsidian'; -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; import { getDetachedFolder, getExcludedFolder, addExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; import { getFolder, getFolderNote } from 'src/functions/folderNoteFunctions'; import { getFileExplorer } from './utils'; import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; -import FolderOverviewPlugin from 'src/obsidian-folder-overview/src/main'; +import type FolderOverviewPlugin from 'src/obsidian-folder-overview/src/main'; /** * @description Refreshes the CSS classes for all folder notes in the file explorer. @@ -156,9 +156,9 @@ export function removeCSSClassFromFileExplorerEL(path: string | undefined, cssCl parentElement.removeClass(cssClass); } return; - } else { - fileExplorerItem.removeClass(cssClass); } + fileExplorerItem.removeClass(cssClass); + } export function getFileExplorerElement(path: string, plugin: FolderNotesPlugin | FolderOverviewPlugin): HTMLElement | null { diff --git a/src/functions/utils.ts b/src/functions/utils.ts index c50a5e7..468c5de 100644 --- a/src/functions/utils.ts +++ b/src/functions/utils.ts @@ -1,9 +1,9 @@ import { TFolder, TFile, View } from 'obsidian'; -import { FileExplorerWorkspaceLeaf, FileExplorerView } from 'src/globals'; +import type { FileExplorerWorkspaceLeaf, FileExplorerView } from 'src/globals'; import { getFolderNote } from './folderNoteFunctions'; -import FolderNotesPlugin from 'src/main'; -import { FileExplorerLeaf } from 'obsidian-typings'; -import FolderOverviewPlugin from 'src/obsidian-folder-overview/src/main'; +import type FolderNotesPlugin from 'src/main'; +import type { FileExplorerLeaf } from 'obsidian-typings'; +import type FolderOverviewPlugin from 'src/obsidian-folder-overview/src/main'; export function getFileNameFromPathString(path: string): string { return path.substring(path.lastIndexOf('/') >= 0 ? path.lastIndexOf('/') + 1 : 0); @@ -12,9 +12,9 @@ export function getFileNameFromPathString(path: string): string { export function getFolderNameFromPathString(path: string): string { if (path.endsWith('.md') || path.endsWith('.canvas')) { return path.split('/').slice(-2)[0]; - } else { - return path.split('/').slice(-1)[0]; } + return path.split('/').slice(-1)[0]; + } export function removeExtension(name: string): string { @@ -30,9 +30,9 @@ export function getFolderPathFromString(path: string): string { const folderPath = path.substring(0, subString); if (folderPath === '') { return '/'; - } else { - return folderPath; } + return folderPath; + } export function getParentFolderPath(path: string): string { @@ -49,7 +49,7 @@ export function getFileExplorerView(plugin: FolderNotesPlugin) { export function getFocusedItem(plugin: FolderNotesPlugin) { const fileExplorer = getFileExplorer(plugin) as any as FileExplorerLeaf; - const focusedItem = fileExplorer.view.tree.focusedItem; + const { focusedItem } = fileExplorer.view.tree; return focusedItem; } diff --git a/src/globals.d.ts b/src/globals.d.ts index ffe085a..1229822 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -1,4 +1,4 @@ -import { TAbstractFile, TFile, TFolder, View, WorkspaceLeaf } from 'obsidian'; +import type { TAbstractFile, TFile, TFolder, View, WorkspaceLeaf } from 'obsidian'; declare module 'obsidian' { interface Setting { diff --git a/src/main.ts b/src/main.ts index a3920c3..b72609a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,10 @@ -import { Plugin, TFile, TFolder, TAbstractFile, MarkdownPostProcessorContext, parseYaml, Notice, Keymap, WorkspaceLeaf, requireApiVersion, Platform, debounce } from 'obsidian'; -import { DEFAULT_SETTINGS, FolderNotesSettings, SettingsTab } from './settings/SettingsTab'; +import type { TAbstractFile, MarkdownPostProcessorContext, WorkspaceLeaf } from 'obsidian'; +import { Plugin, TFile, TFolder, parseYaml, Notice, Keymap, requireApiVersion, Platform, debounce } from 'obsidian'; +import type { FolderNotesSettings } from './settings/SettingsTab'; +import { DEFAULT_SETTINGS, SettingsTab } from './settings/SettingsTab'; import { Commands } from './Commands'; -import { FileExplorerWorkspaceLeaf } from './globals'; +import type { FileExplorerWorkspaceLeaf } from './globals'; import { registerFileExplorerObserver, unregisterFileExplorerObserver } from './events/MutationObserver'; import { handleRename } from './events/handleRename'; import { getFolderNote, getFolder, openFolderNote, createFolderNote } from './functions/folderNoteFunctions'; @@ -15,7 +17,7 @@ import './functions/ListComponent'; import { handleDelete } from './events/handleDelete'; import { addCSSClassToFileExplorerEl, getFileExplorerElement, removeCSSClassFromFileExplorerEL, refreshAllFolderStyles, setActiveFolder, removeActiveFolder } from './functions/styleFunctions'; import { getExcludedFolder } from './ExcludeFolders/functions/folderFunctions'; -import { FileExplorerView, InternalPlugin } from 'obsidian-typings'; +import type { FileExplorerView, InternalPlugin } from 'obsidian-typings'; // import { getFocusedItem } from './functions/utils'; import { FOLDER_OVERVIEW_VIEW, FolderOverviewView } from './obsidian-folder-overview/src/view'; import { registerOverviewCommands } from './obsidian-folder-overview/src/Commands'; @@ -89,7 +91,7 @@ export default class FolderNotesPlugin extends Plugin { // openFolderNote(this, folderNote); // } - const hoveredElement = this.hoveredElement; + const { hoveredElement } = this; if (this.hoverLinkTriggered) return; if (!hoveredElement) return; if (!Keymap.isModEvent(event)) return; @@ -212,7 +214,7 @@ export default class FolderNotesPlugin extends Plugin { const originalHandleDrop = clipboardProto.handleDrop; clipboardProto.handleDragOver = function (evt: DragEvent, ...args: any[]) { - const dragManager = this.app.dragManager; + const { dragManager } = this.app; const draggable = dragManager?.draggable; if (draggable?.file instanceof TFolder) { @@ -227,7 +229,7 @@ export default class FolderNotesPlugin extends Plugin { }; clipboardProto.handleDrop = function (evt: DragEvent, ...args: any[]) { - const dragManager = this.app.dragManager; + const { dragManager } = this.app; const draggable = dragManager?.draggable; if (draggable?.file instanceof TFolder) { @@ -383,9 +385,9 @@ export default class FolderNotesPlugin extends Plugin { } } return folder.children.length <= threshold + 1; - } else { - return false; } + return false; + } return true; } diff --git a/src/modals/AddSupportedFileType.ts b/src/modals/AddSupportedFileType.ts index 7a54f94..c4e802d 100644 --- a/src/modals/AddSupportedFileType.ts +++ b/src/modals/AddSupportedFileType.ts @@ -1,6 +1,7 @@ -import { App, Modal, Setting, Notice, SettingTab } from 'obsidian'; -import FolderNotesPlugin from '../main'; -import { ListComponent } from 'src/functions/ListComponent'; +import type { App, SettingTab } from 'obsidian'; +import { Modal, Setting, Notice } from 'obsidian'; +import type FolderNotesPlugin from '../main'; +import type { ListComponent } from 'src/functions/ListComponent'; export default class AddSupportedFileModal extends Modal { plugin: FolderNotesPlugin; @@ -34,7 +35,7 @@ export default class AddSupportedFileModal extends Modal { if (value.trim() !== '') { this.name = value.trim(); } - }) + }), ); } async onClose() { diff --git a/src/modals/AskForExtension.ts b/src/modals/AskForExtension.ts index 27811c9..50b5ee8 100644 --- a/src/modals/AskForExtension.ts +++ b/src/modals/AskForExtension.ts @@ -1,5 +1,6 @@ -import { FuzzySuggestModal, TFile } from 'obsidian'; -import FolderNotesPlugin from 'src/main'; +import type { TFile } from 'obsidian'; +import { FuzzySuggestModal } from 'obsidian'; +import type FolderNotesPlugin from 'src/main'; import { createFolderNote } from 'src/functions/folderNoteFunctions'; export class AskForExtensionModal extends FuzzySuggestModal { plugin: FolderNotesPlugin; diff --git a/src/modals/DeleteConfirmation.ts b/src/modals/DeleteConfirmation.ts index 9307745..c179ec4 100644 --- a/src/modals/DeleteConfirmation.ts +++ b/src/modals/DeleteConfirmation.ts @@ -1,5 +1,6 @@ -import { App, Modal, TFile, Platform } from 'obsidian'; -import FolderNotesPlugin from '../main'; +import type { App, TFile } from 'obsidian'; +import { Modal, Platform } from 'obsidian'; +import type FolderNotesPlugin from '../main'; import { deleteFolderNote } from 'src/functions/folderNoteFunctions'; export default class DeleteConfirmationModal extends Modal { plugin: FolderNotesPlugin; diff --git a/src/modals/ExistingNote.ts b/src/modals/ExistingNote.ts index 0babd5e..d3c680c 100644 --- a/src/modals/ExistingNote.ts +++ b/src/modals/ExistingNote.ts @@ -1,5 +1,6 @@ -import { App, Modal, Setting, TFile, Platform, TFolder, TAbstractFile } from 'obsidian'; -import FolderNotesPlugin from '../main'; +import type { App, TFile, TFolder, TAbstractFile } from 'obsidian'; +import { Modal, Setting, Platform } from 'obsidian'; +import type FolderNotesPlugin from '../main'; import { turnIntoFolderNote } from 'src/functions/folderNoteFunctions'; export default class ExistingFolderNoteModal extends Modal { plugin: FolderNotesPlugin; diff --git a/src/modals/FolderName.ts b/src/modals/FolderName.ts index 77f6c1c..bdef456 100644 --- a/src/modals/FolderName.ts +++ b/src/modals/FolderName.ts @@ -1,5 +1,6 @@ -import { App, Modal, Setting, TFolder } from 'obsidian'; -import FolderNotesPlugin from '../main'; +import type { App, TFolder } from 'obsidian'; +import { Modal, Setting } from 'obsidian'; +import type FolderNotesPlugin from '../main'; export default class FolderNameModal extends Modal { plugin: FolderNotesPlugin; app: App; @@ -30,7 +31,7 @@ export default class FolderNameModal extends Modal { this.plugin.app.fileManager.renameFile(this.folder, this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + value.trim()); } } - }) + }), ); } onClose() { diff --git a/src/modals/NewFolderName.ts b/src/modals/NewFolderName.ts index 59a35bf..64fa454 100644 --- a/src/modals/NewFolderName.ts +++ b/src/modals/NewFolderName.ts @@ -1,5 +1,6 @@ -import { App, Modal, TFolder } from 'obsidian'; -import FolderNotesPlugin from '../main'; +import type { App, TFolder } from 'obsidian'; +import { Modal } from 'obsidian'; +import type FolderNotesPlugin from '../main'; export default class NewFolderNameModal extends Modal { plugin: FolderNotesPlugin; app: App; diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index f1d2495..07825d6 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit f1d24952999f23e2912c7e6c2da4bd53325d2402 +Subproject commit 07825d6f187a9ddf2c9b29066eb0c06aa8b8fee2 diff --git a/src/settings/ExcludedFoldersSettings.ts b/src/settings/ExcludedFoldersSettings.ts index 6c21b86..e4126fb 100644 --- a/src/settings/ExcludedFoldersSettings.ts +++ b/src/settings/ExcludedFoldersSettings.ts @@ -2,7 +2,7 @@ import { addExcludeFolderListItem, addExcludedFolder } from 'src/ExcludeFolders/ import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; import { addExcludePatternListItem } from 'src/ExcludeFolders/functions/patternFunctions'; import { Setting } from 'obsidian'; -import { SettingsTab } from './SettingsTab'; +import type { SettingsTab } from './SettingsTab'; import ExcludedFolderSettings from 'src/ExcludeFolders/modals/ExcludeFolderSettings'; import PatternSettings from 'src/ExcludeFolders/modals/PatternSettings'; import WhitelistedFoldersSettings from 'src/ExcludeFolders/modals/WhitelistedFoldersSettings'; diff --git a/src/settings/FileExplorerSettings.ts b/src/settings/FileExplorerSettings.ts index e408014..0d79841 100644 --- a/src/settings/FileExplorerSettings.ts +++ b/src/settings/FileExplorerSettings.ts @@ -1,5 +1,5 @@ import { Setting } from 'obsidian'; -import { SettingsTab } from './SettingsTab'; +import type { SettingsTab } from './SettingsTab'; export async function renderFileExplorer(settingsTab: SettingsTab) { const containerEl = settingsTab.settingsPage; @@ -18,7 +18,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { document.body.classList.remove('hide-folder-note'); } settingsTab.display(); - }) + }), ); const setting2 = new Setting(containerEl) @@ -30,7 +30,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { .onChange(async (value) => { settingsTab.plugin.settings.disableOpenFolderNoteOnClick = value; await settingsTab.plugin.saveSettings(); - }) + }), ); setting2.infoEl.appendText('Requires a restart to take effect'); @@ -50,7 +50,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { } settingsTab.plugin.settings.stopWhitespaceCollapsing = !value; await settingsTab.plugin.saveSettings(); - }) + }), ); const disableSetting = new Setting(containerEl); @@ -62,7 +62,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { .onChange(async (value) => { settingsTab.plugin.settings.enableCollapsing = !value; await settingsTab.plugin.saveSettings(); - }) + }), ); disableSetting.infoEl.appendText('Requires a restart to take effect'); disableSetting.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; @@ -77,7 +77,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { settingsTab.plugin.settings.useSubmenus = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); if (settingsTab.plugin.settings.frontMatterTitle.enabled) { @@ -93,7 +93,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { settingsTab.plugin.app.vault.getFiles().forEach((file) => { settingsTab.plugin.fmtpHandler?.fmptUpdateFileName({ id: '', result: false, path: file.path, pathOnly: false }, false); }); - }) + }), ); } @@ -113,7 +113,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { document.body.classList.remove('disable-folder-highlight'); } await settingsTab.plugin.saveSettings(); - }) + }), ); new Setting(containerEl) @@ -131,7 +131,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { document.body.classList.remove('fn-hide-collapse-icon'); } settingsTab.display(); - }) + }), ); new Setting(containerEl) @@ -149,7 +149,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { document.body.classList.remove('fn-hide-empty-collapse-icon'); } settingsTab.display(); - } + }, )); if (settingsTab.plugin.settings.hideCollapsingIcon) { @@ -161,7 +161,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { .onChange(async (value) => { settingsTab.plugin.settings.ignoreAttachmentFolder = value; await settingsTab.plugin.saveSettings(); - }) + }), ); } @@ -179,7 +179,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { document.body.classList.remove('folder-note-underline'); } await settingsTab.plugin.saveSettings(); - }) + }), ); new Setting(containerEl) @@ -196,7 +196,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { document.body.classList.remove('folder-note-bold'); } await settingsTab.plugin.saveSettings(); - }) + }), ); new Setting(containerEl) @@ -213,7 +213,7 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { document.body.classList.remove('folder-note-cursive'); } await settingsTab.plugin.saveSettings(); - }) + }), ); } diff --git a/src/settings/FolderOverviewSettings.ts b/src/settings/FolderOverviewSettings.ts index b06c6d4..310fb1e 100644 --- a/src/settings/FolderOverviewSettings.ts +++ b/src/settings/FolderOverviewSettings.ts @@ -1,5 +1,5 @@ import { Setting } from 'obsidian'; -import { SettingsTab } from './SettingsTab'; +import type { SettingsTab } from './SettingsTab'; import { createOverviewSettings } from 'src/obsidian-folder-overview/src/settings'; export async function renderFolderOverview(settingsTab: SettingsTab) { @@ -22,7 +22,7 @@ export async function renderFolderOverview(settingsTab: SettingsTab) { } else { plugin.fvIndexDB.active = false; } - }) + }), ); containerEl.createEl('h3', { text: 'Overviews default settings' }); diff --git a/src/settings/GeneralSettings.ts b/src/settings/GeneralSettings.ts index 495361e..3a15b8e 100644 --- a/src/settings/GeneralSettings.ts +++ b/src/settings/GeneralSettings.ts @@ -1,5 +1,5 @@ import { Setting, Platform } from 'obsidian'; -import { SettingsTab } from './SettingsTab'; +import type { SettingsTab } from './SettingsTab'; import { ListComponent } from '../functions/ListComponent'; import AddSupportedFileModal from '../modals/AddSupportedFileType'; import { FrontMatterTitlePluginHandler } from '../events/FrontMatterTitle'; @@ -38,7 +38,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { } } }, 2000); - }) + }), ) .addButton((button) => button @@ -52,7 +52,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.renameFolderNotes, []) .open(); - }) + }), ); nameSetting.infoEl.appendText('Requires a restart to take effect'); nameSetting.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; @@ -74,7 +74,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.tabManagerEnabled = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); } @@ -115,7 +115,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { setting0.setName('Supported file types'); const desc0 = document.createDocumentFragment(); desc0.append( - 'Specify which file types are allowed as folder notes. Applies to both new and existing folders. Adding many types may affect performance.' + 'Specify which file types are allowed as folder notes. Applies to both new and existing folders. Adding many types may affect performance.', ); setting0.setDesc(desc0); const list = new ListComponent(setting0.settingEl, settingsTab.plugin.settings.supportedFileTypes || [], ['md', 'canvas']); @@ -158,7 +158,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { .setCta() .onClick(async () => { new AddSupportedFileModal(settingsTab.app, settingsTab.plugin, settingsTab, list as ListComponent).open(); - }) + }), ); } @@ -195,7 +195,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { await settingsTab.plugin.saveSettings(); settingsTab.display(); refreshAllFolderStyles(undefined, settingsTab.plugin); - }) + }), ) .addButton((button) => button @@ -213,9 +213,9 @@ export async function renderGeneral(settingsTab: SettingsTab) { 'Switch storage location', 'When you click on "Confirm" all folder notes will be moved to the new storage location.', settingsTab.switchStorageLocation, - [oldStorageLocation] + [oldStorageLocation], ).open(); - }) + }), ); storageLocation.infoEl.appendText('Requires a restart to take effect'); storageLocation.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; @@ -230,8 +230,8 @@ export async function renderGeneral(settingsTab: SettingsTab) { .onChange(async (value) => { settingsTab.plugin.settings.syncDelete = value; await settingsTab.plugin.saveSettings(); - } - ) + }, + ), ); new Setting(containerEl) .setName('Move folder notes when moving the folder') @@ -242,7 +242,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { .onChange(async (value) => { settingsTab.plugin.settings.syncMove = value; await settingsTab.plugin.saveSettings(); - }) + }), ); } if (Platform.isDesktopApp) { @@ -309,7 +309,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.showDeleteConfirmation = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); new Setting(containerEl) @@ -338,7 +338,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.openInNewTab = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); setting3.infoEl.appendText('Requires a restart to take effect'); setting3.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; @@ -355,7 +355,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.focusExistingTab = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); } @@ -369,7 +369,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.syncFolderName = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); settingsTab.settingsPage.createEl('h4', { text: 'Automation settings' }); @@ -395,7 +395,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.autoCreate = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); if (settingsTab.plugin.settings.autoCreate) { @@ -409,7 +409,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.autoCreateFocusFiles = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); new Setting(containerEl) @@ -422,7 +422,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.autoCreateForAttachmentFolder = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); } @@ -436,7 +436,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.autoCreateForFiles = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); settingsTab.settingsPage.createEl('h3', { text: 'Integration & Compatibility' }); @@ -476,7 +476,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.fmtpHandler = new FrontMatterTitlePluginHandler(settingsTab.plugin); } settingsTab.display(); - }) + }), ); fmtpSetting.infoEl.appendText('Requires a restart to take effect'); fmtpSetting.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; @@ -493,7 +493,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.persistentSettingsTab.afterRestart = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); new Setting(containerEl) @@ -506,6 +506,6 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.persistentSettingsTab.afterChangingTab = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); } diff --git a/src/settings/PathSettings.ts b/src/settings/PathSettings.ts index eb8499f..3ea8be2 100644 --- a/src/settings/PathSettings.ts +++ b/src/settings/PathSettings.ts @@ -1,5 +1,5 @@ import { Setting } from 'obsidian'; -import { SettingsTab } from './SettingsTab'; +import type { SettingsTab } from './SettingsTab'; export async function renderPath(settingsTab: SettingsTab) { const containerEl = settingsTab.settingsPage; new Setting(containerEl) @@ -12,7 +12,7 @@ export async function renderPath(settingsTab: SettingsTab) { settingsTab.plugin.settings.openFolderNoteOnClickInPath = value; await settingsTab.plugin.saveSettings(); settingsTab.display(); - }) + }), ); if (settingsTab.plugin.settings.openFolderNoteOnClickInPath) { @@ -25,7 +25,7 @@ export async function renderPath(settingsTab: SettingsTab) { .onChange(async (value) => { settingsTab.plugin.settings.openSidebar.mobile = value; await settingsTab.plugin.saveSettings(); - }) + }), ); new Setting(containerEl) @@ -37,7 +37,7 @@ export async function renderPath(settingsTab: SettingsTab) { .onChange(async (value) => { settingsTab.plugin.settings.openSidebar.desktop = value; await settingsTab.plugin.saveSettings(); - }) + }), ); } @@ -56,7 +56,7 @@ export async function renderPath(settingsTab: SettingsTab) { } else { settingsTab.plugin.updateAllBreadcrumbs(true); } - }) + }), ); } @@ -76,7 +76,7 @@ export async function renderPath(settingsTab: SettingsTab) { document.body.classList.remove('folder-note-underline-path'); } await settingsTab.plugin.saveSettings(); - }) + }), ); new Setting(containerEl) @@ -93,7 +93,7 @@ export async function renderPath(settingsTab: SettingsTab) { document.body.classList.remove('folder-note-bold-path'); } await settingsTab.plugin.saveSettings(); - }) + }), ); new Setting(containerEl) @@ -110,6 +110,6 @@ export async function renderPath(settingsTab: SettingsTab) { document.body.classList.remove('folder-note-cursive-path'); } await settingsTab.plugin.saveSettings(); - }) + }), ); } diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index 15d62ab..e6723c8 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -1,17 +1,18 @@ -import { App, Notice, PluginSettingTab, TFile, TFolder, MarkdownPostProcessorContext } from 'obsidian'; -import FolderNotesPlugin from '../main'; -import { ExcludePattern } from 'src/ExcludeFolders/ExcludePattern'; -import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; +import type { App, MarkdownPostProcessorContext } from 'obsidian'; +import { Notice, PluginSettingTab, TFile, TFolder } from 'obsidian'; +import type FolderNotesPlugin from '../main'; +import type { ExcludePattern } from 'src/ExcludeFolders/ExcludePattern'; +import type { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; import { extractFolderName, getFolderNote } from '../functions/folderNoteFunctions'; -import { defaultOverviewSettings } from '../obsidian-folder-overview/src/FolderOverview'; +import type { defaultOverviewSettings } from '../obsidian-folder-overview/src/FolderOverview'; import { renderGeneral } from './GeneralSettings'; import { renderFileExplorer } from './FileExplorerSettings'; import { renderPath } from './PathSettings'; import { renderFolderOverview } from './FolderOverviewSettings'; import { renderExcludeFolders } from './ExcludedFoldersSettings'; import { getFolderPathFromString } from '../functions/utils'; -import { WhitelistedFolder } from 'src/ExcludeFolders/WhitelistFolder'; -import { WhitelistedPattern } from 'src/ExcludeFolders/WhitelistPattern'; +import type { WhitelistedFolder } from 'src/ExcludeFolders/WhitelistFolder'; +import type { WhitelistedPattern } from 'src/ExcludeFolders/WhitelistPattern'; export interface FolderNotesSettings { syncFolderName: boolean; @@ -348,10 +349,10 @@ export class SettingsTab extends PluginSettingTab { } else if (this.plugin.settings.storageLocation === 'insideFolder') { if (getFolderPathFromString(folderNote.path) === file.path) { return; - } else { - const newPath = `${file.path}/${folderNote.name}`; - this.plugin.app.fileManager.renameFile(folderNote, newPath); } + const newPath = `${file.path}/${folderNote.name}`; + this.plugin.app.fileManager.renameFile(folderNote, newPath); + } } } diff --git a/src/settings/modals/BackupWarning.ts b/src/settings/modals/BackupWarning.ts index 98db472..a0deb27 100644 --- a/src/settings/modals/BackupWarning.ts +++ b/src/settings/modals/BackupWarning.ts @@ -1,5 +1,5 @@ import { Modal, ButtonComponent } from 'obsidian'; -import FolderNotesPlugin from 'src/main'; +import type FolderNotesPlugin from 'src/main'; export default class BackupWarningModal extends Modal { plugin: FolderNotesPlugin; diff --git a/src/settings/modals/CreateFnForEveryFolder.ts b/src/settings/modals/CreateFnForEveryFolder.ts index c3e719a..0380886 100644 --- a/src/settings/modals/CreateFnForEveryFolder.ts +++ b/src/settings/modals/CreateFnForEveryFolder.ts @@ -1,5 +1,6 @@ -import { App, ButtonComponent, Modal, Setting, TFolder, Notice } from 'obsidian'; -import FolderNotesPlugin from '../../main'; +import type { App, ButtonComponent } from 'obsidian'; +import { Modal, Setting, TFolder, Notice } from 'obsidian'; +import type FolderNotesPlugin from '../../main'; import { createFolderNote, getFolderNote } from 'src/functions/folderNoteFunctions'; import { getTemplatePlugins } from 'src/template'; import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; @@ -46,7 +47,7 @@ export default class ConfirmationModal extends Modal { cb.onChange(async (value) => { this.extension = value; }); - } + }, ); } new Setting(contentEl) diff --git a/src/settings/modals/RenameFns.ts b/src/settings/modals/RenameFns.ts index f4f6667..56cd925 100644 --- a/src/settings/modals/RenameFns.ts +++ b/src/settings/modals/RenameFns.ts @@ -1,5 +1,5 @@ import BackupWarningModal from './BackupWarning'; -import FolderNotesPlugin from 'src/main'; +import type FolderNotesPlugin from 'src/main'; import { Setting } from 'obsidian'; export default class RenameFolderNotesModal extends BackupWarningModal { @@ -17,7 +17,7 @@ export default class RenameFolderNotesModal extends BackupWarningModal { .setValue(this.plugin.settings.oldFolderNoteName || '') .onChange(async (value) => { this.plugin.settings.oldFolderNoteName = value; - }) + }), ); new Setting(contentEl) @@ -29,7 +29,7 @@ export default class RenameFolderNotesModal extends BackupWarningModal { .onChange(async (value) => { this.plugin.settings.folderNoteName = value; this.plugin.settingsTab.display(); - }) + }), ); } } diff --git a/src/suggesters/FileSuggester.ts b/src/suggesters/FileSuggester.ts index 09777da..941ba8d 100644 --- a/src/suggesters/FileSuggester.ts +++ b/src/suggesters/FileSuggester.ts @@ -1,8 +1,9 @@ // Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater -import { TAbstractFile, TFile } from 'obsidian'; +import type { TAbstractFile } from 'obsidian'; +import { TFile } from 'obsidian'; import { TextInputSuggest } from './Suggest'; -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; export enum FileSuggestMode { TemplateFiles, ScriptFiles, @@ -11,7 +12,7 @@ export enum FileSuggestMode { export class FileSuggest extends TextInputSuggest { constructor( public inputEl: HTMLInputElement, - plugin: FolderNotesPlugin + plugin: FolderNotesPlugin, ) { super(inputEl, plugin); } diff --git a/src/suggesters/FolderSuggester.ts b/src/suggesters/FolderSuggester.ts index 4b156d5..e3d07b6 100644 --- a/src/suggesters/FolderSuggester.ts +++ b/src/suggesters/FolderSuggester.ts @@ -1,8 +1,9 @@ // Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater -import { TAbstractFile, TFolder } from 'obsidian'; +import type { TAbstractFile } from 'obsidian'; +import { TFolder } from 'obsidian'; import { TextInputSuggest } from './Suggest'; -import FolderNotesPlugin from '../main'; +import type FolderNotesPlugin from '../main'; export enum FileSuggestMode { TemplateFiles, ScriptFiles, diff --git a/src/suggesters/Suggest.ts b/src/suggesters/Suggest.ts index fa92e75..4a3fb02 100644 --- a/src/suggesters/Suggest.ts +++ b/src/suggesters/Suggest.ts @@ -1,9 +1,11 @@ // Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater -import { ISuggestOwner, Scope } from 'obsidian'; -import { createPopper, Instance as PopperInstance } from '@popperjs/core'; -import FolderNotesPlugin from 'src/main'; +import type { ISuggestOwner } from 'obsidian'; +import { Scope } from 'obsidian'; +import type { Instance as PopperInstance } from '@popperjs/core'; +import { createPopper } from '@popperjs/core'; +import type FolderNotesPlugin from 'src/main'; const wrapAround = (value: number, size: number): number => { return ((value % size) + size) % size; @@ -20,7 +22,7 @@ class Suggest { constructor( owner: ISuggestOwner, containerEl: HTMLElement, - scope: Scope + scope: Scope, ) { this.owner = owner; this.containerEl = containerEl; @@ -28,12 +30,12 @@ class Suggest { containerEl.on( 'click', '.suggestion-item', - this.onSuggestionClick.bind(this) + this.onSuggestionClick.bind(this), ); containerEl.on( 'mousemove', '.suggestion-item', - this.onSuggestionMouseover.bind(this) + this.onSuggestionMouseover.bind(this), ); scope.register([], 'ArrowUp', (event) => { @@ -96,7 +98,7 @@ class Suggest { setSelectedItem(selectedIndex: number, scrollIntoView: boolean) { const normalizedIndex = wrapAround( selectedIndex, - this.suggestions.length + this.suggestions.length, ); const prevSelectedSuggestion = this.suggestions[this.selectedItem]; const selectedSuggestion = this.suggestions[normalizedIndex]; @@ -140,7 +142,7 @@ export abstract class TextInputSuggest implements ISuggestOwner { '.suggestion-container', (event: MouseEvent) => { event.preventDefault(); - } + }, ); } @@ -163,7 +165,7 @@ export abstract class TextInputSuggest implements ISuggestOwner { } open(container: HTMLElement, inputEl: HTMLElement): void { - // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.plugin.app.keymap.pushScope(this.scope); container.appendChild(this.suggestEl); diff --git a/src/suggesters/TemplateSuggester.ts b/src/suggesters/TemplateSuggester.ts index 7290f62..0e26932 100644 --- a/src/suggesters/TemplateSuggester.ts +++ b/src/suggesters/TemplateSuggester.ts @@ -1,5 +1,6 @@ -import { TAbstractFile, TFile, TFolder, Vault, AbstractInputSuggest } from 'obsidian'; -import FolderNotesPlugin from '../main'; +import type { TAbstractFile } from 'obsidian'; +import { TFile, TFolder, Vault, AbstractInputSuggest } from 'obsidian'; +import type FolderNotesPlugin from '../main'; import { getTemplatePlugins } from 'src/template'; export enum FileSuggestMode { TemplateFiles, @@ -9,7 +10,7 @@ export enum FileSuggestMode { export class TemplateSuggest extends AbstractInputSuggest { constructor( public inputEl: HTMLInputElement, - public plugin: FolderNotesPlugin + public plugin: FolderNotesPlugin, ) { super(plugin.app, inputEl); } @@ -32,13 +33,13 @@ export class TemplateSuggest extends AbstractInputSuggest { if ((!templateFolder || templateFolder.trim() === '') && !templaterPlugin) { files = this.plugin.app.vault.getFiles().filter((file) => - file.path.toLowerCase().includes(lower_input_str) + file.path.toLowerCase().includes(lower_input_str), ); } else { let folder: TFolder | TAbstractFile | null = null; if (templaterPlugin) { folder = this.plugin.app.vault.getAbstractFileByPath( - templaterPlugin.plugin?.settings?.templates_folder as string + templaterPlugin.plugin?.settings?.templates_folder as string, ); if (!(folder instanceof TFolder)) { return [{ path: '', name: 'You need to set the Templates folder in the Templater settings first.' } as TFile]; diff --git a/src/template.ts b/src/template.ts index 7d6914e..4855c52 100644 --- a/src/template.ts +++ b/src/template.ts @@ -1,11 +1,12 @@ -import { TFile, App, WorkspaceLeaf } from 'obsidian'; -import FolderNotesPlugin from './main'; +import type { App } from 'obsidian'; +import { TFile, WorkspaceLeaf } from 'obsidian'; +import type FolderNotesPlugin from './main'; export async function applyTemplate( plugin: FolderNotesPlugin, file: TFile, leaf?: WorkspaceLeaf | null, - templatePath?: string + templatePath?: string, ) { const fileContent = await plugin.app.vault.read(file).catch((err) => { console.error(`Error reading file ${file.path}:`, err); @@ -37,9 +38,9 @@ export async function applyTemplate( await leaf.openFile(file); } return await templatesPlugin.instance.insertTemplate(templateFile); - } else { - await plugin.app.vault.modify(file, templateContent); } + await plugin.app.vault.modify(file, templateContent); + } catch (e) { console.error(e); From 8adf6186ac159d4b3e8cdb5aff1a1a452d5000d8 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Fri, 8 Aug 2025 09:37:35 +0200 Subject: [PATCH 23/47] Fix linter issues for the events folder --- eslint.config.mts | 11 +- src/events/EventEmitter.ts | 8 +- src/events/FrontMatterTitle.ts | 74 +++++--- src/events/MutationObserver.ts | 54 ++++-- src/events/TabManager.ts | 14 +- src/events/handleClick.ts | 92 ++++++--- src/events/handleCreate.ts | 21 +- src/events/handleDelete.ts | 25 ++- src/events/handleRename.ts | 327 +++++++++++++++++++++++--------- src/main.ts | 13 +- src/obsidian-folder-overview | 2 +- src/suggesters/FileSuggester.ts | 5 +- src/template.ts | 3 +- 13 files changed, 437 insertions(+), 212 deletions(-) diff --git a/eslint.config.mts b/eslint.config.mts index bb047f9..fcf59e4 100644 --- a/eslint.config.mts +++ b/eslint.config.mts @@ -139,18 +139,23 @@ export default [ 'no-empty-function': 'warn', 'complexity': [ 'warn', - 10 + 15 ], 'max-len': [ 'warn', { - code: 100 + code: 100, + ignoreComments: true, } ], 'no-inline-comments': 'warn', 'no-magic-numbers': [ 'warn', { ignore: [0, 1], - enforceConst: true + enforceConst: true, + ignoreTypeIndexes: true, + ignoreEnums: true, + ignoreNumericLiteralTypes: true, + ignoreClassFieldInitialValues: true, } ], } diff --git a/src/events/EventEmitter.ts b/src/events/EventEmitter.ts index a5ba33e..607fb07 100644 --- a/src/events/EventEmitter.ts +++ b/src/events/EventEmitter.ts @@ -1,20 +1,20 @@ export class CustomEventEmitter { - private events: { [key: string]: Array<(data?: any) => void> } = {}; + private events: { [key: string]: Array<(data?: unknown) => void> } = {}; - on(event: string, listener: (data?: any) => void) { + on(event: string, listener: (data?: unknown) => void): void { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(listener); } - off(event: string, listener: (data?: any) => void) { + off(event: string, listener: (data?: unknown) => void): void { if (!this.events[event]) return; this.events[event] = this.events[event].filter((l) => l !== listener); } - emit(event: string, data?: any) { + emit(event: string, data?: unknown): void { if (!this.events[event]) return; this.events[event].forEach((listener) => listener(data)); diff --git a/src/events/FrontMatterTitle.ts b/src/events/FrontMatterTitle.ts index 3586346..e694c87 100644 --- a/src/events/FrontMatterTitle.ts +++ b/src/events/FrontMatterTitle.ts @@ -1,9 +1,28 @@ import type FolderNotesPlugin from 'src/main'; -import type { Listener, Events, ApiInterface, DeferInterface, ListenerRef, EventDispatcherInterface } from 'front-matter-plugin-api-provider'; -import { getDefer } from 'front-matter-plugin-api-provider'; -import type { App } from 'obsidian'; -import { TFile, TFolder } from 'obsidian'; +import { + type Listener, + type Events, + type ApiInterface, + type DeferInterface, + type ListenerRef, + type EventDispatcherInterface, + getDefer, +} from 'front-matter-plugin-api-provider'; +import { type App, TFile, TFolder } from 'obsidian'; import { getFolder, getFolderNote } from 'src/functions/folderNoteFunctions'; + +interface UpdateData { + id: string; + result: boolean; + path: string; + pathOnly: boolean; + breadcrumb?: HTMLElement; +} + +interface WrappedUpdateData { + data: UpdateData; +} + export class FrontMatterTitlePluginHandler { plugin: FolderNotesPlugin; app: App; @@ -16,7 +35,7 @@ export class FrontMatterTitlePluginHandler { this.plugin = plugin; this.app = plugin.app; - (async () => { + (async (): Promise => { this.deffer = getDefer(this.app); if (this.deffer.isPluginReady()) { this.api = this.deffer.getApi(); @@ -35,8 +54,8 @@ export class FrontMatterTitlePluginHandler { } const event: Listener = { name: 'manager:update', - cb: (data) => { - this.fmptUpdateFileName(data as any, true); + cb: (data): void => { + this.fmptUpdateFileName(data as unknown as UpdateData, true); }, }; // Keep ref to remove listener @@ -51,20 +70,18 @@ export class FrontMatterTitlePluginHandler { } })(); } - deleteEvent() { + + deleteEvent(): void { if (this.eventRef) { this.dispatcher.removeListener(this.eventRef); } } - async fmptUpdateFileName(data: { - id: string; - result: boolean; - path: string; - pathOnly: boolean; - breadcrumb?: HTMLElement; - }, isEvent: boolean) { - if ((data as any).data) data = (data as any).data; - const file = this.app.vault.getAbstractFileByPath(data.path); + async fmptUpdateFileName(data: UpdateData, isEvent: boolean): Promise { + const hasNestedData = 'data' in (data as unknown as Record); + const actualData: UpdateData = hasNestedData + ? (data as unknown as WrappedUpdateData).data + : data; + const file = this.app.vault.getAbstractFileByPath(actualData.path); if (!(file instanceof TFile)) { return; } const resolver = this.api?.getResolverFactory()?.createResolver('#feature-id#'); @@ -75,11 +92,11 @@ export class FrontMatterTitlePluginHandler { const folderNote = getFolderNote(this.plugin, folder.path); if (!folderNote) { return; } if (folderNote !== file) { return; } - if (!data.pathOnly) { + if (!actualData.pathOnly) { this.plugin.changeFolderNameInExplorer(folder, newName); } - const { breadcrumb } = data; + const { breadcrumb } = actualData; if (breadcrumb) { this.plugin.changeFolderNameInPath(folder, newName, breadcrumb); } @@ -98,15 +115,12 @@ export class FrontMatterTitlePluginHandler { } - async fmptUpdateFolderName(data: { - id: string; - result: boolean; - path: string; - pathOnly: boolean; - breadcrumb?: HTMLElement; - }, replacePath: boolean) { - if ((data as any).data) data = (data as any).data; - const folder = this.app.vault.getAbstractFileByPath(data.path); + async fmptUpdateFolderName(data: UpdateData, _replacePath: boolean): Promise { + const hasNestedData = 'data' in (data as unknown as Record); + const actualData: UpdateData = hasNestedData + ? (data as unknown as WrappedUpdateData).data + : data; + const folder = this.app.vault.getAbstractFileByPath(actualData.path); if (!(folder instanceof TFolder)) { return; } const folderNote = getFolderNote(this.plugin, folder.path); if (!folderNote) { return; } @@ -115,11 +129,11 @@ export class FrontMatterTitlePluginHandler { const newName = resolver?.resolve(folderNote?.path ?? ''); if (!newName) return; - if (!data.pathOnly) { + if (!actualData.pathOnly) { this.plugin.changeFolderNameInExplorer(folder, newName); } - const { breadcrumb } = data; + const { breadcrumb } = actualData; if (breadcrumb) { this.plugin.changeFolderNameInPath(folder, newName, breadcrumb); } diff --git a/src/events/MutationObserver.ts b/src/events/MutationObserver.ts index a03a5e0..1a6a01d 100644 --- a/src/events/MutationObserver.ts +++ b/src/events/MutationObserver.ts @@ -7,7 +7,7 @@ import { updateCSSClassesForFolder } from 'src/functions/styleFunctions'; let fileExplorerMutationObserver: MutationObserver | null = null; -export function registerFileExplorerObserver(plugin: FolderNotesPlugin) { +export function registerFileExplorerObserver(plugin: FolderNotesPlugin): void { // Run once on initial layout plugin.app.workspace.onLayoutReady(() => { initializeFolderNoteFeatures(plugin); @@ -30,19 +30,19 @@ export function registerFileExplorerObserver(plugin: FolderNotesPlugin) { ); } -export function unregisterFileExplorerObserver() { +export function unregisterFileExplorerObserver(): void { if (fileExplorerMutationObserver) { fileExplorerMutationObserver.disconnect(); fileExplorerMutationObserver = null; } } -function initializeFolderNoteFeatures(plugin: FolderNotesPlugin) { +function initializeFolderNoteFeatures(plugin: FolderNotesPlugin): void { initializeAllFolderTitles(plugin); observeFolderTitleMutations(plugin); } -function initializeBreadcrumbs(plugin: FolderNotesPlugin) { +function initializeBreadcrumbs(plugin: FolderNotesPlugin): void { const titleContainers = document.querySelectorAll('.view-header-title-container'); if (!titleContainers.length) return; titleContainers.forEach((container) => { @@ -55,7 +55,7 @@ function initializeBreadcrumbs(plugin: FolderNotesPlugin) { * Observes the File Explorer for newly added folder elements and applies plugin logic (e.g., styles, event listeners) * automatically when folders are created, expanded, or when the File Explorer view is reopened. */ -function observeFolderTitleMutations(plugin: FolderNotesPlugin) { +function observeFolderTitleMutations(plugin: FolderNotesPlugin): void { if (fileExplorerMutationObserver) { fileExplorerMutationObserver.disconnect(); } @@ -71,7 +71,7 @@ function observeFolderTitleMutations(plugin: FolderNotesPlugin) { fileExplorerMutationObserver.observe(document, { childList: true, subtree: true }); } -function initializeAllFolderTitles(plugin: FolderNotesPlugin) { +function initializeAllFolderTitles(plugin: FolderNotesPlugin): void { const allTitles = document.querySelectorAll('.nav-folder-title-content'); for (const title of Array.from(allTitles)) { const folderTitle = title as HTMLElement; @@ -83,7 +83,7 @@ function initializeAllFolderTitles(plugin: FolderNotesPlugin) { } } -function processAddedFolders(node: HTMLElement, plugin: FolderNotesPlugin) { +function processAddedFolders(node: HTMLElement, plugin: FolderNotesPlugin): void { const titles: HTMLElement[] = []; if (node.matches('.nav-folder-title-content')) { titles.push(node); @@ -95,6 +95,7 @@ function processAddedFolders(node: HTMLElement, plugin: FolderNotesPlugin) { titles.forEach((folderTitle) => { const folderEl = folderTitle.closest('.nav-folder-title'); const folderPath = folderEl?.getAttribute('data-path') || ''; + const RETRY_TIMEOUT = 50; if (!folderEl || !folderPath) { setTimeout(() => { const retryFolderEl = folderTitle.closest('.nav-folder-title'); @@ -102,14 +103,18 @@ function processAddedFolders(node: HTMLElement, plugin: FolderNotesPlugin) { if (retryFolderEl && retryFolderPath) { setupFolderTitle(folderTitle, plugin, retryFolderPath); } - }, 50); + }, RETRY_TIMEOUT); return; } setupFolderTitle(folderTitle, plugin, folderPath); }); } -async function setupFolderTitle(folderTitle: HTMLElement, plugin: FolderNotesPlugin, folderPath: string) { +async function setupFolderTitle( + folderTitle: HTMLElement, + plugin: FolderNotesPlugin, + folderPath: string, +): Promise { if (folderTitle.dataset.initialized === 'true') return; if (!folderPath) return; @@ -117,7 +122,10 @@ async function setupFolderTitle(folderTitle: HTMLElement, plugin: FolderNotesPlu await updateCSSClassesForFolder(folderPath, plugin); if (plugin.settings.frontMatterTitle.enabled) { - plugin.fmtpHandler?.fmptUpdateFolderName({ id: '', result: false, path: folderPath, pathOnly: false }, false); + plugin.fmtpHandler?.fmptUpdateFolderName( + { id: '', result: false, path: folderPath, pathOnly: false }, + false, + ); } if (Platform.isMobile && plugin.settings.disableOpenFolderNoteOnClick) return; @@ -150,21 +158,24 @@ async function setupFolderTitle(folderTitle: HTMLElement, plugin: FolderNotesPlu }); } -async function updateFolderNamesInPath(plugin: FolderNotesPlugin, titleContainer: HTMLElement) { +async function updateFolderNamesInPath( + plugin: FolderNotesPlugin, + titleContainer: HTMLElement, +): Promise { const headers = titleContainer.querySelectorAll('span.view-header-breadcrumb'); let path = ''; + const TRAILING_SLASH_LENGTH = 1; headers.forEach(async (breadcrumb: HTMLElement) => { path += breadcrumb.getAttribute('old-name') ?? (breadcrumb as HTMLElement).innerText.trim(); path += '/'; - const folderPath = path.slice(0, -1); + const folderPath = path.slice(0, -TRAILING_SLASH_LENGTH); const excludedFolder = getExcludedFolder(plugin, folderPath, true); if (excludedFolder?.disableFolderNote) return; const folderNote = getFolderNote(plugin, folderPath); if (!folderNote) return; if (folderNote) breadcrumb.classList.add('has-folder-note'); - - breadcrumb?.setAttribute('data-path', path.slice(0, -1)); + breadcrumb?.setAttribute('data-path', path.slice(0, -TRAILING_SLASH_LENGTH)); if (!breadcrumb.onclick) { breadcrumb.addEventListener('click', (e) => { handleViewHeaderClick(e as MouseEvent, plugin); @@ -172,7 +183,10 @@ async function updateFolderNamesInPath(plugin: FolderNotesPlugin, titleContainer } if (plugin.settings.frontMatterTitle.enabled) { - plugin.fmtpHandler?.fmptUpdateFolderName({ id: '', result: false, path: folderPath, pathOnly: true, breadcrumb: breadcrumb }, true); + plugin.fmtpHandler?.fmptUpdateFolderName( + { id: '', result: false, path: folderPath, pathOnly: true, breadcrumb: breadcrumb }, + true, + ); } }); } @@ -180,10 +194,14 @@ async function updateFolderNamesInPath(plugin: FolderNotesPlugin, titleContainer // Schedules a callback to run when the browser is idle, or after a timeout as a fallback. // - callback: The function to execute when idle or after the timeout. // - options: Optional object with a 'timeout' property (in milliseconds). -function scheduleIdle(callback: () => void, options?: { timeout: number }) { +function scheduleIdle(callback: () => void, options?: { timeout: number }): void { + const DEFAULT_IDLE_TIMEOUT = 200; if ('requestIdleCallback' in window) { - (window as any).requestIdleCallback(callback, options); + const windowWithIdle = window as Window & { + requestIdleCallback: (callback: () => void, options?: { timeout: number }) => void + }; + windowWithIdle.requestIdleCallback(callback, options); } else { - setTimeout(callback, options?.timeout || 200); + setTimeout(callback, options?.timeout || DEFAULT_IDLE_TIMEOUT); } } diff --git a/src/events/TabManager.ts b/src/events/TabManager.ts index 11903ff..c9647bb 100644 --- a/src/events/TabManager.ts +++ b/src/events/TabManager.ts @@ -1,6 +1,5 @@ import type FolderNotesPlugin from 'src/main'; -import type { App } from 'obsidian'; -import { EditableFileView, TFolder } from 'obsidian'; +import { EditableFileView, TFolder, type App } from 'obsidian'; import { getFolder, getFolderNote } from 'src/functions/folderNoteFunctions'; export class TabManager { plugin: FolderNotesPlugin; @@ -10,19 +9,18 @@ export class TabManager { this.app = plugin.app; } - resetTabs() { + resetTabs(): void { if (!this.isEnabled()) return; this.app.workspace.iterateAllLeaves((leaf) => { if (!(leaf.view instanceof EditableFileView)) return; const file = leaf.view?.file; if (!file) return; - // @ts-ignore leaf.tabHeaderInnerTitleEl.setText(file.basename); }); } - updateTabs() { + updateTabs(): void { if (!this.isEnabled()) return; this.app.workspace.iterateAllLeaves((leaf) => { if (!(leaf.view instanceof EditableFileView)) return; @@ -30,12 +28,11 @@ export class TabManager { if (!file) return; const folder = getFolder(this.plugin, file); if (!folder) return; - // @ts-ignore leaf.tabHeaderInnerTitleEl.setText(folder.name); }); } - updateTab(folderPath: string) { + updateTab(folderPath: string): void { if (!this.isEnabled()) return; const folder = this.app.vault.getAbstractFileByPath(folderPath); @@ -49,13 +46,12 @@ export class TabManager { const file = leaf.view?.file; if (!file) return; if (file.path === folderNote.path) { - // @ts-ignore leaf.tabHeaderInnerTitleEl.setText(folder.name); } }); } - isEnabled() { + isEnabled(): boolean { if (this.plugin.settings.folderNoteName === '{{folder_name}}') return false; return this.plugin.settings.tabManagerEnabled; } diff --git a/src/events/handleClick.ts b/src/events/handleClick.ts index fb8dc6f..60ecabd 100644 --- a/src/events/handleClick.ts +++ b/src/events/handleClick.ts @@ -1,10 +1,18 @@ -import { Keymap, Platform } from 'obsidian'; +import { Keymap, Platform, type TFile } from 'obsidian'; import type FolderNotesPlugin from 'src/main'; import { openFolderNote, createFolderNote, getFolderNote } from 'src/functions/folderNoteFunctions'; import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; -import { addCSSClassToFileExplorerEl, removeCSSClassFromFileExplorerEL } from 'src/functions/styleFunctions'; +import { + addCSSClassToFileExplorerEl, + removeCSSClassFromFileExplorerEL, +} from 'src/functions/styleFunctions'; -export async function handleViewHeaderClick(event: MouseEvent, plugin: FolderNotesPlugin) { + + +export async function handleViewHeaderClick( + event: MouseEvent, + plugin: FolderNotesPlugin, +): Promise { if (!plugin.settings.openFolderNoteOnClickInPath) return; event.stopImmediatePropagation(); event.preventDefault(); @@ -13,37 +21,61 @@ export async function handleViewHeaderClick(event: MouseEvent, plugin: FolderNot const folderPath = event.target.getAttribute('data-path'); if (!folderPath) { return; } - const excludedFolder = getExcludedFolder(plugin, folderPath, true); - if (excludedFolder?.disableFolderNote) { - event.target.onclick = null; - event.target.click(); - return; - } else if (excludedFolder?.enableCollapsing || plugin.settings.enableCollapsing) { - event.target.onclick = null; - event.target.click(); - } + + if (await isExcludedFolder(event, plugin, folderPath)) return; const folderNote = getFolderNote(plugin, folderPath); if (folderNote) { - await openFolderNote(plugin, folderNote, event).then(async () => { - // @ts-ignore - const fileExplorerPlugin = plugin.app.internalPlugins.getEnabledPluginById('file-explorer'); - if (fileExplorerPlugin && Platform.isMobile && plugin.settings.openSidebar.mobile) { - setTimeout(() => { fileExplorerPlugin.revealInFolder(folderNote); }, 200); - } else if (fileExplorerPlugin && Platform.isDesktop && plugin.settings.openSidebar.desktop) { - fileExplorerPlugin.revealInFolder(folderNote); - } - }); + await openFolderNote(plugin, folderNote, event).then(() => + handleFolderNoteReveal(plugin, folderNote), + ); return; } else if (event.altKey || Keymap.isModEvent(event) === 'tab') { - const usedCtrl = Platform.isMacOS ? event.metaKey : event.ctrlKey; - if ((plugin.settings.altKey && event.altKey) || (usedCtrl && Keymap.isModEvent(event) === 'tab')) { - await createFolderNote(plugin, folderPath, true, undefined, true); - addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, plugin); - removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, plugin); - return; - } + if (await handleFolderNoteCreation(event, plugin, folderPath)) return; + } + (event.target as HTMLElement).onclick = null; + (event.target as HTMLElement).click(); +} + +async function isExcludedFolder( + event: MouseEvent, + plugin: FolderNotesPlugin, + folderPath: string, +): Promise { + const excludedFolder = getExcludedFolder(plugin, folderPath, true); + if (excludedFolder?.disableFolderNote) { + (event.target as HTMLElement).onclick = null; + (event.target as HTMLElement).click(); + return true; + } else if (excludedFolder?.enableCollapsing || plugin.settings.enableCollapsing) { + (event.target as HTMLElement).onclick = null; + (event.target as HTMLElement).click(); + } + return false; +} + +async function handleFolderNoteReveal(plugin: FolderNotesPlugin, folderNote: TFile): Promise { + const fileExplorerPlugin = plugin.app.internalPlugins.getEnabledPluginById('file-explorer'); + if (fileExplorerPlugin && Platform.isMobile && plugin.settings.openSidebar.mobile) { + const OPEN_SIDEBAR_DELAY = 200; + setTimeout(() => { fileExplorerPlugin.revealInFolder(folderNote); }, OPEN_SIDEBAR_DELAY); + } else if (fileExplorerPlugin && Platform.isDesktop && plugin.settings.openSidebar.desktop) { + fileExplorerPlugin.revealInFolder(folderNote); + } +} + +async function handleFolderNoteCreation( + event: MouseEvent, + plugin: FolderNotesPlugin, + folderPath: string, +): Promise { + const usedCtrl = Platform.isMacOS ? event.metaKey : event.ctrlKey; + if ((plugin.settings.altKey && event.altKey) || + (usedCtrl && Keymap.isModEvent(event) === 'tab')) { + await createFolderNote(plugin, folderPath, true, undefined, true); + addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, plugin); + removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, plugin); + return true; } - event.target.onclick = null; - event.target.click(); + return false; } diff --git a/src/events/handleCreate.ts b/src/events/handleCreate.ts index f65d3ed..c6239c3 100644 --- a/src/events/handleCreate.ts +++ b/src/events/handleCreate.ts @@ -1,11 +1,18 @@ -import type { TAbstractFile } from 'obsidian'; -import { TFolder, TFile } from 'obsidian'; +import { TFolder, TFile, type TAbstractFile } from 'obsidian'; import type FolderNotesPlugin from 'src/main'; -import { createFolderNote, getFolder, getFolderNote, turnIntoFolderNote } from 'src/functions/folderNoteFunctions'; +import { + createFolderNote, + getFolder, + getFolderNote, + turnIntoFolderNote, +} from 'src/functions/folderNoteFunctions'; import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; -import { removeCSSClassFromFileExplorerEL, addCSSClassToFileExplorerEl } from 'src/functions/styleFunctions'; +import { + removeCSSClassFromFileExplorerEL, + addCSSClassToFileExplorerEl, +} from 'src/functions/styleFunctions'; -export async function handleCreate(file: TAbstractFile, plugin: FolderNotesPlugin) { +export async function handleCreate(file: TAbstractFile, plugin: FolderNotesPlugin): Promise { if (!plugin.app.workspace.layoutReady) return; const folder = file.parent; @@ -24,7 +31,7 @@ export async function handleCreate(file: TAbstractFile, plugin: FolderNotesPlugi } } -async function handleFileCreation(file: TFile, plugin: FolderNotesPlugin) { +async function handleFileCreation(file: TFile, plugin: FolderNotesPlugin): Promise { const folder = getFolder(plugin, file); if (!(folder instanceof TFolder) && plugin.settings.autoCreateForFiles) { @@ -51,7 +58,7 @@ async function handleFileCreation(file: TFile, plugin: FolderNotesPlugin) { } } -async function handleFolderCreation(folder: TFolder, plugin: FolderNotesPlugin) { +async function handleFolderCreation(folder: TFolder, plugin: FolderNotesPlugin): Promise { let openFile = plugin.settings.autoCreateFocusFiles; const attachmentFolderPath = plugin.app.vault.getConfig('attachmentFolderPath') as string; diff --git a/src/events/handleDelete.ts b/src/events/handleDelete.ts index 089c1ff..e9d5c51 100644 --- a/src/events/handleDelete.ts +++ b/src/events/handleDelete.ts @@ -1,11 +1,14 @@ -import type { TAbstractFile } from 'obsidian'; -import { TFolder, TFile } from 'obsidian'; +import { TFolder, TFile, type TAbstractFile } from 'obsidian'; import type FolderNotesPlugin from 'src/main'; import { getFolderNote, getFolder, deleteFolderNote } from 'src/functions/folderNoteFunctions'; -import { removeCSSClassFromFileExplorerEL, addCSSClassToFileExplorerEl, hideFolderNoteInFileExplorer } from 'src/functions/styleFunctions'; +import { + removeCSSClassFromFileExplorerEL, + addCSSClassToFileExplorerEl, + hideFolderNoteInFileExplorer, +} from 'src/functions/styleFunctions'; import { getFolderPathFromString } from 'src/functions/utils'; -export function handleDelete(file: TAbstractFile, plugin: FolderNotesPlugin) { +export function handleDelete(file: TAbstractFile, plugin: FolderNotesPlugin): void { const folder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(file.path)); if (folder instanceof TFolder) { if (plugin.isEmptyFolderNoteFolder(folder) && getFolderNote(plugin, folder.path)) { @@ -16,13 +19,15 @@ export function handleDelete(file: TAbstractFile, plugin: FolderNotesPlugin) { } if (file instanceof TFile) { - const folder = getFolder(plugin, file); - if (!folder) { return; } - const folderNote = getFolderNote(plugin, folder.path); + const folderNoteFolder = getFolder(plugin, file); + if (!folderNoteFolder) { return; } + const folderNote = getFolderNote(plugin, folderNoteFolder.path); if (folderNote) { return; } - removeCSSClassFromFileExplorerEL(folder.path, 'has-folder-note', false, plugin); - removeCSSClassFromFileExplorerEL(folder.path, 'only-has-folder-note', true, plugin); - hideFolderNoteInFileExplorer(folder.path, plugin); + removeCSSClassFromFileExplorerEL(folderNoteFolder.path, 'has-folder-note', false, plugin); + removeCSSClassFromFileExplorerEL( + folderNoteFolder.path, 'only-has-folder-note', true, plugin, + ); + hideFolderNoteInFileExplorer(folderNoteFolder.path, plugin); } if (!(file instanceof TFolder)) { return; } diff --git a/src/events/handleRename.ts b/src/events/handleRename.ts index 7ca75b2..c6fb0ea 100644 --- a/src/events/handleRename.ts +++ b/src/events/handleRename.ts @@ -1,14 +1,29 @@ -import type { TAbstractFile } from 'obsidian'; -import { TFile, TFolder, Notice } from 'obsidian'; +import { TFile, TFolder, Notice, type TAbstractFile } from 'obsidian'; import type FolderNotesPlugin from 'src/main'; -import { extractFolderName, getFolderNote, getFolderNoteFolder } from '../functions/folderNoteFunctions'; -import { getExcludedFolder, addExcludedFolder, updateExcludedFolder, deleteExcludedFolder, getDetachedFolder } from '../ExcludeFolders/functions/folderFunctions'; +import { + extractFolderName, getFolderNote, getFolderNoteFolder, +} from '../functions/folderNoteFunctions'; +import { + getExcludedFolder, addExcludedFolder, + updateExcludedFolder, deleteExcludedFolder, getDetachedFolder, +} from '../ExcludeFolders/functions/folderFunctions'; import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; -import { removeCSSClassFromFileExplorerEL, addCSSClassToFileExplorerEl, markFileAsFolderNote, unmarkFileAsFolderNote, unmarkFolderAsFolderNote, markFolderWithFolderNoteClasses, hideFolderNoteInFileExplorer, removeActiveFolder, setActiveFolder } from 'src/functions/styleFunctions'; -import { getFolderPathFromString, removeExtension, getFileNameFromPathString } from 'src/functions/utils'; - -export function handleRename(file: TAbstractFile, oldPath: string, plugin: FolderNotesPlugin) { - const folder = file.parent; +import { + removeCSSClassFromFileExplorerEL, addCSSClassToFileExplorerEl, + markFileAsFolderNote, unmarkFileAsFolderNote, + unmarkFolderAsFolderNote, markFolderWithFolderNoteClasses, + hideFolderNoteInFileExplorer, removeActiveFolder, setActiveFolder, +} from 'src/functions/styleFunctions'; +import { + getFolderPathFromString, removeExtension, getFileNameFromPathString, +} from 'src/functions/utils'; + +export function handleRename( + file: TAbstractFile, + oldPath: string, + plugin: FolderNotesPlugin, +): void { + let folder = file.parent; const oldFolder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(oldPath)); if (folder instanceof TFolder) { @@ -28,19 +43,22 @@ export function handleRename(file: TAbstractFile, oldPath: string, plugin: Folde } if (file instanceof TFolder) { - const folder = file; + folder = file; plugin.tabManager.updateTab(folder.path); updateExcludedFolderPath(folder, oldPath, plugin); if (isFolderRename(folder, oldPath)) { - return handleFolderRename(folder, oldPath, plugin); + handleFolderRename(folder, oldPath, plugin); + return; } return handleFolderMove(folder, oldPath, plugin); } else if (file instanceof TFile) { if (isFileRename(file, oldPath)) { - return fmptUpdateFileName(file, oldPath, plugin); + handleFileRename(file, oldPath, plugin); + return; } - return handleFileMove(file, oldPath, plugin); + handleFileMove(file, oldPath, plugin); + return; } } @@ -64,7 +82,7 @@ function isFolderRename(folder: TFolder, oldPath: string): boolean { return oldParent === newParent && oldName !== newName; } -export function handleFolderMove(file: TFolder, oldPath: string, plugin: FolderNotesPlugin) { +export function handleFolderMove(file: TFolder, oldPath: string, plugin: FolderNotesPlugin): void { if (plugin.settings.storageLocation === 'insideFolder') { return; } if (!plugin.settings.syncMove) { return; } const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation); @@ -82,60 +100,43 @@ export function handleFolderMove(file: TFolder, oldPath: string, plugin: FolderN plugin.app.fileManager.renameFile(folderNote, newPath); } -export async function handleFileMove(file: TFile, oldPath: string, plugin: FolderNotesPlugin) { - const folderName = extractFolderName(plugin.settings.folderNoteName, file.basename) || file.basename; - const oldFileName = removeExtension(getFileNameFromPathString(oldPath)); - const newFolder = getFolderNoteFolder(plugin, file, file.basename); - let excludedFolder = getExcludedFolder(plugin, newFolder?.path || '', true); - const oldFolder = getFolderNoteFolder(plugin, oldPath, oldFileName); - const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation, file); - +// eslint-disable-next-line complexity +export async function handleFileMove( + file: TFile, + oldPath: string, + plugin: FolderNotesPlugin, +): Promise { + const { folderName, oldFileName, newFolder, excludedFolder, oldFolder, folderNote } = getArgs( + plugin, file, oldPath, + ); - const isFileNowFolderNoteInNewFolder = folderName === newFolder?.name; - const isFileMovedFromOldFolderNote = oldFolder && oldFolder.name === oldFileName && newFolder?.path !== oldFolder.path; + const isFolderNoteInNewFolder = folderName === newFolder?.name; + const fileMovedFromOldFolderNote = oldFolder && oldFolder.name === oldFileName + && newFolder?.path !== oldFolder.path; // this is for turning files into folder notes for folders that already have a folder note // e.g. Turn into folder note for "Folder name" - const isFileNowFolderNoteWithExistingNote = folderName === newFolder?.name && folderNote; - - if (isFileNowFolderNoteWithExistingNote) { - let excludedFolderExisted = true; - let disabledSync = false; - - if (!excludedFolder) { - excludedFolderExisted = false; - excludedFolder = new ExcludedFolder(oldFolder?.path || '', plugin.settings.excludeFolders.length, undefined, plugin); - addExcludedFolder(plugin, excludedFolder); - } else if (!excludedFolder.disableSync) { - disabledSync = false; - excludedFolder.disableSync = true; - updateExcludedFolder(plugin, excludedFolder, excludedFolder); - } - return plugin.app.fileManager.renameFile(file, oldPath).then(() => { - if (!excludedFolder) { return; } - if (!excludedFolderExisted) { - deleteExcludedFolder(plugin, excludedFolder); - } else if (!disabledSync) { - excludedFolder.disableSync = false; - updateExcludedFolder(plugin, excludedFolder, excludedFolder); - } - }); - } else if (isFileNowFolderNoteInNewFolder) { - if (!excludedFolder?.disableFolderNote) { - markFileAsFolderNote(file, plugin); - if (newFolder instanceof TFolder) { - markFolderWithFolderNoteClasses(newFolder, plugin); - if (plugin.app.workspace.getActiveFile()?.path === file.path) { - removeActiveFolder(plugin); - setActiveFolder(newFolder.path, plugin); - } - } - if (oldFolder instanceof TFolder) { - hideFolderNoteInFileExplorer(oldFolder.path, plugin); - unmarkFolderAsFolderNote(oldFolder, plugin); + const isFileWithExistingNote = folderName === newFolder?.name && folderNote; + + if (isFileWithExistingNote) { + renameExistingFolderNote( + file, oldPath, plugin, excludedFolder, oldFolder, + ); + } else if (isFolderNoteInNewFolder) { + if (excludedFolder?.disableFolderNote) { return; } + markFileAsFolderNote(file, plugin); + if (newFolder instanceof TFolder) { + markFolderWithFolderNoteClasses(newFolder, plugin); + if (plugin.app.workspace.getActiveFile()?.path === file.path) { + removeActiveFolder(plugin); + setActiveFolder(newFolder.path, plugin); } } - } else if (isFileMovedFromOldFolderNote) { + if (oldFolder instanceof TFolder) { + hideFolderNoteInFileExplorer(oldFolder.path, plugin); + unmarkFolderAsFolderNote(oldFolder, plugin); + } + } else if (fileMovedFromOldFolderNote) { unmarkFileAsFolderNote(file, plugin); if (oldFolder instanceof TFolder) { removeActiveFolder(plugin); @@ -145,9 +146,75 @@ export async function handleFileMove(file: TFile, oldPath: string, plugin: Folde } } -export async function handleFolderRename(file: TFolder, oldPath: string, plugin: FolderNotesPlugin) { + + +function getArgs(plugin: FolderNotesPlugin, file: TFile, oldPath: string): { + folderName: string; + oldFileName: string; + newFolder: TAbstractFile | null; + excludedFolder: ExcludedFolder | undefined; + oldFolder: TAbstractFile | null; + folderNote: TFile | null | undefined; +} { + const folderName = extractFolderName(plugin.settings.folderNoteName, file.basename) + || file.basename; + const oldFileName = removeExtension(getFileNameFromPathString(oldPath)); + const newFolder = getFolderNoteFolder(plugin, file, file.basename); + let excludedFolder = getExcludedFolder(plugin, newFolder?.path || '', true); + const oldFolder = getFolderNoteFolder(plugin, oldPath, oldFileName); + const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation, file); + + return { + folderName, + oldFileName, + newFolder, + excludedFolder, + oldFolder, + folderNote, + }; +} + +function renameExistingFolderNote( + file: TFile, oldPath: string, plugin: FolderNotesPlugin, + excludedFolder: ExcludedFolder | undefined, + oldFolder: TAbstractFile | null, +): void { + let excludedFolderExisted = true; + let disabledSync = false; + + if (!excludedFolder) { + excludedFolderExisted = false; + excludedFolder = new ExcludedFolder( + oldFolder?.path || '', + plugin.settings.excludeFolders.length, + undefined, + plugin, + ); + addExcludedFolder(plugin, excludedFolder); + } else if (!excludedFolder.disableSync) { + disabledSync = false; + excludedFolder.disableSync = true; + updateExcludedFolder(plugin, excludedFolder, excludedFolder); + } + plugin.app.fileManager.renameFile(file, oldPath).then(() => { + if (!excludedFolder) { return; } + if (!excludedFolderExisted) { + deleteExcludedFolder(plugin, excludedFolder); + } else if (!disabledSync) { + excludedFolder.disableSync = false; + updateExcludedFolder(plugin, excludedFolder, excludedFolder); + } + }); +} + + + +export async function handleFolderRename( + file: TFolder, oldPath: string, plugin: FolderNotesPlugin, +): Promise { const fileName = plugin.settings.folderNoteName.replace('{{folder_name}}', file.name); - const oldFileName = plugin.settings.folderNoteName.replace('{{folder_name}}', getFileNameFromPathString(oldPath)); + const oldFileName = plugin.settings.folderNoteName + .replace('{{folder_name}}', getFileNameFromPathString(oldPath)); if (fileName === oldFileName) { return; } @@ -183,50 +250,62 @@ export async function handleFolderRename(file: TFolder, oldPath: string, plugin: plugin.app.fileManager.renameFile(folderNote, newPath); } -export async function fmptUpdateFileName(file: TFile, oldPath: string, plugin: FolderNotesPlugin) { +// eslint-disable-next-line complexity +export async function handleFileRename( + file: TFile, + oldPath: string, + plugin: FolderNotesPlugin, +): Promise { const oldFileName = removeExtension(getFileNameFromPathString(oldPath)); const newFileName = file.basename; if (oldFileName === newFileName) { return; } const oldFolder = getFolderNoteFolder(plugin, oldPath, oldFileName); - const folderName = extractFolderName(plugin.settings.folderNoteName, file.basename) || file.basename; - const oldFolderName = extractFolderName(plugin.settings.folderNoteName, oldFileName) || oldFileName; + const folderName = extractFolderName(plugin.settings.folderNoteName, file.basename) + || file.basename; + const oldFolderName = extractFolderName(plugin.settings.folderNoteName, oldFileName) + || oldFileName; const newFolder = getFolderNoteFolder(plugin, file, file.basename); const excludedFolder = getExcludedFolder(plugin, newFolder?.path || '', true); const detachedExcludedFolder = getDetachedFolder(plugin, newFolder?.path || ''); const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation, file); - if (!excludedFolder?.disableFolderNote && folderName === newFolder?.name && !detachedExcludedFolder) { - addCSSClassToFileExplorerEl(file.path, 'is-folder-note', false, plugin); - addCSSClassToFileExplorerEl(newFolder.path, 'has-folder-note', false, plugin); + // Handle folder note creation + if (shouldCreateFolderNote(excludedFolder, folderName, newFolder, detachedExcludedFolder)) { + if (newFolder) { + handleFolderNoteCreation(file, newFolder, plugin); + } return; - } else if (excludedFolder?.disableFolderNote || (folderName !== newFolder?.name)) { - removeCSSClassFromFileExplorerEL(file.path, 'is-folder-note', false, plugin); - removeCSSClassFromFileExplorerEL(newFolder?.path || '', 'has-folder-note', false, plugin); } - if (excludedFolder?.disableSync || !plugin.settings.syncFolderName) { return; } + // Handle folder note removal + if (shouldRemoveFolderNoteClasses(excludedFolder, folderName, newFolder)) { + handleFolderNoteRemoval(file, newFolder, plugin); + } + // Early return if sync is disabled + if (excludedFolder?.disableSync || !plugin.settings.syncFolderName) { + return; + } - if (folderName === newFolder?.name) { - addCSSClassToFileExplorerEl(file.path, 'is-folder-note', false, plugin); - removeCSSClassFromFileExplorerEL(oldFolder?.path, 'has-folder-note', false, plugin); - addCSSClassToFileExplorerEl(newFolder.path, 'has-folder-note', false, plugin); + // Handle same folder rename + if (folderName === newFolder?.name && newFolder) { + handleSameFolderRename(file, newFolder, oldFolder, plugin); return; } - // file matched folder name before rename - // file hasnt moved just renamed - // Need to rename the folder - if (!oldFolder) return; - if (oldFolderName === oldFolder.name && newFolder?.path === oldFolder.path) { - return renameFolderOnFileRename(file, oldPath, oldFolder, plugin); - } else if (folderNote && oldFolderName === oldFolder.name) { - return renameFolderOnFileRename(file, oldPath, oldFolder, plugin); + // Handle folder rename on file rename + if (shouldRenameFolderOnFileRename(oldFolderName, oldFolder, newFolder, folderNote)) { + return renameFolderOnFileRename(file, oldPath, oldFolder!, plugin); } } -async function renameFolderOnFileRename(file: TFile, oldPath: string, oldFolder: TAbstractFile, plugin: FolderNotesPlugin) { +async function renameFolderOnFileRename( + file: TFile, + oldPath: string, + oldFolder: TAbstractFile, + plugin: FolderNotesPlugin, +): Promise { const newFolderName = extractFolderName(plugin.settings.folderNoteName, file.basename); if (!newFolderName) { removeCSSClassFromFileExplorerEL(oldFolder.path, 'has-folder-note', false, plugin); @@ -256,12 +335,17 @@ async function renameFolderOnFileRename(file: TFile, oldPath: string, oldFolder: if (plugin.app.vault.getAbstractFileByPath(newFolderPath)) { await plugin.app.fileManager.renameFile(file, oldPath); - return new Notice('A folder with the same name already exists'); + new Notice('A folder with the same name already exists'); + return; } plugin.app.fileManager.renameFile(oldFolder, newFolderPath); } -function updateExcludedFolderPath(folder: TFolder, oldPath: string, plugin: FolderNotesPlugin) { +function updateExcludedFolderPath( + folder: TFolder, + oldPath: string, + plugin: FolderNotesPlugin, +): void { const excludedFolders = plugin.settings.excludeFolders.filter( (excludedFolder) => excludedFolder.path?.includes(oldPath), ); @@ -282,3 +366,68 @@ function updateExcludedFolderPath(folder: TFolder, oldPath: string, plugin: Fold }); plugin.saveSettings(); } + + +function shouldCreateFolderNote( + excludedFolder: ExcludedFolder | undefined, + folderName: string, + newFolder: TAbstractFile | null, + detachedExcludedFolder: ExcludedFolder | undefined, +): boolean { + return !excludedFolder?.disableFolderNote + && folderName === (newFolder as TFolder)?.name + && !detachedExcludedFolder; +} + +function shouldRemoveFolderNoteClasses( + excludedFolder: ExcludedFolder | undefined, + folderName: string, + newFolder: TAbstractFile | null, +): boolean { + return excludedFolder?.disableFolderNote || (folderName !== (newFolder as TFolder)?.name); +} + +function handleFolderNoteCreation( + file: TFile, + newFolder: TAbstractFile, + plugin: FolderNotesPlugin, +): void { + addCSSClassToFileExplorerEl(file.path, 'is-folder-note', false, plugin); + addCSSClassToFileExplorerEl(newFolder.path, 'has-folder-note', false, plugin); +} + +function handleFolderNoteRemoval( + file: TFile, + newFolder: TAbstractFile | null, + plugin: FolderNotesPlugin, +): void { + removeCSSClassFromFileExplorerEL(file.path, 'is-folder-note', false, plugin); + removeCSSClassFromFileExplorerEL(newFolder?.path || '', 'has-folder-note', false, plugin); +} + +function handleSameFolderRename( + file: TFile, + newFolder: TAbstractFile, + oldFolder: TAbstractFile | null, + plugin: FolderNotesPlugin, +): void { + addCSSClassToFileExplorerEl(file.path, 'is-folder-note', false, plugin); + removeCSSClassFromFileExplorerEL(oldFolder?.path, 'has-folder-note', false, plugin); + addCSSClassToFileExplorerEl(newFolder.path, 'has-folder-note', false, plugin); +} + +function shouldRenameFolderOnFileRename( + oldFolderName: string, + oldFolder: TAbstractFile | null, + newFolder: TAbstractFile | null, + folderNote: TFile | null | undefined, +): boolean { + if (!oldFolder) return false; + + const oldFolderAsFolder = oldFolder as TFolder; + const newFolderAsFolder = newFolder as TFolder; + + return (oldFolderName === oldFolderAsFolder.name + && newFolderAsFolder?.path === oldFolderAsFolder.path) + || (folderNote !== null && oldFolderName === oldFolderAsFolder.name); +} diff --git a/src/main.ts b/src/main.ts index b72609a..6f18134 100644 --- a/src/main.ts +++ b/src/main.ts @@ -203,7 +203,7 @@ export default class FolderNotesPlugin extends Plugin { // @ts-ignore const editMode = view.editMode ?? view.sourceMode ?? this.app.workspace.activeEditor?.editMode; - // eslint-disable-next-line + const plugin = this; if (!editMode) { return; } @@ -308,7 +308,7 @@ export default class FolderNotesPlugin extends Plugin { openFolderNote(this, folderNote, evt); } - handleOverviewBlock(source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) { + handleOverviewBlock(source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext): void { const observer = new MutationObserver(() => { const editButton = el.parentElement?.childNodes.item(1); if (editButton) { @@ -316,7 +316,10 @@ export default class FolderNotesPlugin extends Plugin { e.stopImmediatePropagation(); e.preventDefault(); e.stopPropagation(); - new FolderOverviewSettings(this.app, this, parseYaml(source), ctx, el, this.settings.defaultOverview).open(); + new FolderOverviewSettings( + this.app, this, parseYaml(source), + ctx, el, this.settings.defaultOverview, + ).open(); }, { capture: true }); } }); @@ -329,11 +332,11 @@ export default class FolderNotesPlugin extends Plugin { try { if (this.app.workspace.layoutReady) { const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverview); - folderOverview.create(this, parseYaml(source), el, ctx); + folderOverview.create(this, el, ctx); } else { this.app.workspace.onLayoutReady(() => { const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverview); - folderOverview.create(this, parseYaml(source), el, ctx); + folderOverview.create(this, el, ctx); }); } } catch (e) { diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 07825d6..5323f27 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 07825d6f187a9ddf2c9b29066eb0c06aa8b8fee2 +Subproject commit 5323f27922aff0165dca78770f24a7d8a99de7c0 diff --git a/src/suggesters/FileSuggester.ts b/src/suggesters/FileSuggester.ts index 941ba8d..3828036 100644 --- a/src/suggesters/FileSuggester.ts +++ b/src/suggesters/FileSuggester.ts @@ -1,7 +1,4 @@ -// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater - -import type { TAbstractFile } from 'obsidian'; -import { TFile } from 'obsidian'; +import { type TAbstractFile, TFile } from 'obsidian'; import { TextInputSuggest } from './Suggest'; import type FolderNotesPlugin from '../main'; export enum FileSuggestMode { diff --git a/src/template.ts b/src/template.ts index 4855c52..09753cb 100644 --- a/src/template.ts +++ b/src/template.ts @@ -1,5 +1,4 @@ -import type { App } from 'obsidian'; -import { TFile, WorkspaceLeaf } from 'obsidian'; +import { TFile, WorkspaceLeaf, type App } from 'obsidian'; import type FolderNotesPlugin from './main'; export async function applyTemplate( From 113cf5f40c9fe71a906207b6497e16a717e440a0 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sun, 10 Aug 2025 12:21:16 +0200 Subject: [PATCH 24/47] Excluded folders --- src/ExcludeFolders/ExcludeFolder.ts | 1 + src/ExcludeFolders/ExcludePattern.ts | 8 +- src/ExcludeFolders/WhitelistPattern.ts | 7 +- .../functions/folderFunctions.ts | 209 +++++++++++++----- .../functions/patternFunctions.ts | 160 ++++++++------ .../functions/whitelistFolderFunctions.ts | 114 +++++++--- .../functions/whitelistPatternFunctions.ts | 164 ++++++++------ .../modals/ExcludeFolderSettings.ts | 11 +- src/ExcludeFolders/modals/PatternSettings.ts | 15 +- .../modals/WhitelistFolderSettings.ts | 12 +- .../modals/WhitelistPatternSettings.ts | 14 +- .../modals/WhitelistedFoldersSettings.ts | 40 ++-- 12 files changed, 494 insertions(+), 261 deletions(-) diff --git a/src/ExcludeFolders/ExcludeFolder.ts b/src/ExcludeFolders/ExcludeFolder.ts index 24af3ab..b080ec2 100644 --- a/src/ExcludeFolders/ExcludeFolder.ts +++ b/src/ExcludeFolders/ExcludeFolder.ts @@ -25,6 +25,7 @@ export class ExcludedFolder { this.disableFolderNote = plugin.settings.excludeFolderDefaultSettings.disableFolderNote; this.enableCollapsing = plugin.settings.excludeFolderDefaultSettings.enableCollapsing; this.position = position; + // eslint-disable-next-line max-len this.excludeFromFolderOverview = plugin.settings.excludeFolderDefaultSettings.excludeFromFolderOverview; this.string = ''; this.hideInSettings = false; diff --git a/src/ExcludeFolders/ExcludePattern.ts b/src/ExcludeFolders/ExcludePattern.ts index c78aab3..971cbba 100644 --- a/src/ExcludeFolders/ExcludePattern.ts +++ b/src/ExcludeFolders/ExcludePattern.ts @@ -15,7 +15,12 @@ export class ExcludePattern { detached: boolean; detachedFilePath?: string; showFolderNote: boolean; - constructor(pattern: string, position: number, id: string | undefined, plugin: FolderNotesPlugin) { + constructor( + pattern: string, + position: number, + id: string | undefined, + plugin: FolderNotesPlugin, + ) { this.type = 'pattern'; this.id = id || crypto.randomUUID(); this.string = pattern; @@ -25,6 +30,7 @@ export class ExcludePattern { this.disableAutoCreate = plugin.settings.excludePatternDefaultSettings.disableAutoCreate; this.disableFolderNote = plugin.settings.excludePatternDefaultSettings.disableFolderNote; this.enableCollapsing = plugin.settings.excludePatternDefaultSettings.enableCollapsing; + // eslint-disable-next-line max-len this.excludeFromFolderOverview = plugin.settings.excludePatternDefaultSettings.excludeFromFolderOverview; this.path = ''; this.hideInSettings = false; diff --git a/src/ExcludeFolders/WhitelistPattern.ts b/src/ExcludeFolders/WhitelistPattern.ts index bf9fe91..506a597 100644 --- a/src/ExcludeFolders/WhitelistPattern.ts +++ b/src/ExcludeFolders/WhitelistPattern.ts @@ -13,7 +13,12 @@ export class WhitelistedPattern { showInFolderOverview: boolean; hideInFileExplorer: boolean; hideInSettings: boolean; - constructor(pattern: string, position: number, id: string | undefined, plugin: FolderNotesPlugin) { + constructor( + pattern: string, + position: number, + id: string | undefined, + plugin: FolderNotesPlugin, + ) { this.type = 'pattern'; this.id = id || crypto.randomUUID(); this.subFolders = plugin.settings.excludePatternDefaultSettings.subFolders; diff --git a/src/ExcludeFolders/functions/folderFunctions.ts b/src/ExcludeFolders/functions/folderFunctions.ts index a2fb61c..8ec4a45 100644 --- a/src/ExcludeFolders/functions/folderFunctions.ts +++ b/src/ExcludeFolders/functions/folderFunctions.ts @@ -6,24 +6,34 @@ import { Platform, Setting } from 'obsidian'; import { FolderSuggest } from '../../suggesters/FolderSuggester'; import type { SettingsTab } from '../../settings/SettingsTab'; import ExcludedFolderSettings from '../modals/ExcludeFolderSettings'; -import { updatePattern, getExcludedFoldersByPattern, addExcludePatternListItem } from './patternFunctions'; +import { + updatePattern, + getExcludedFoldersByPattern, + addExcludePatternListItem, +} from './patternFunctions'; import { getWhitelistedFolder } from './whitelistFolderFunctions'; import type { WhitelistedFolder } from '../WhitelistFolder'; import type { WhitelistedPattern } from '../WhitelistPattern'; -export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, includeDetached: boolean, pathOnly?: boolean, ignoreWhitelist?: boolean) { - let excludedFolder = {} as ExcludedFolder | ExcludePattern | undefined; - const whitelistedFolder = getWhitelistedFolder(plugin, path) as WhitelistedFolder | WhitelistedPattern | undefined; +function combineExcluded( + plugin: FolderNotesPlugin, + path: string, + includeDetached: boolean, + pathOnly?: boolean, +): Array { const folderName = getFolderNameFromPathString(path); - let matchedPatterns = getExcludedFoldersByPattern(plugin, folderName); - const excludedFolders = getExcludedFoldersByPath(plugin, path); - if (pathOnly) { matchedPatterns = []; } - let combinedExcludedFolders = [...matchedPatterns, ...excludedFolders]; - - if (!includeDetached) { - combinedExcludedFolders = combinedExcludedFolders.filter((f) => !f.detached); - } + const matchedPatterns = pathOnly ? [] : getExcludedFoldersByPattern(plugin, folderName); + const excludedByPath = getExcludedFoldersByPath(plugin, path); + let combined = [...matchedPatterns, ...excludedByPath]; + if (!includeDetached) combined = combined.filter((f) => !f.detached); + return combined; +} +function aggregateFlags( + combinedExcludedFolders: Array, +): Partial | undefined { + if (combinedExcludedFolders.length === 0) return undefined; + const result: Partial = {}; const propertiesToCopy: (keyof ExcludedFolder)[] = [ 'disableAutoCreate', 'disableFolderNote', @@ -35,32 +45,46 @@ export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, inclu 'id', 'showFolderNote', ]; - - if (combinedExcludedFolders.length > 0) { - for (const matchedFolder of combinedExcludedFolders) { - propertiesToCopy.forEach((property) => { - if (matchedFolder[property] === true) { - (excludedFolder as any)[property] = true; - } else if (!matchedFolder[property]) { - (excludedFolder as any)[property] = false; - } - }); + for (const matchedFolder of combinedExcludedFolders) { + for (const property of propertiesToCopy) { + const value = (matchedFolder as Partial)[property]; + if (value === true) { + (result as Partial)[property] = true as never; + } else if (!value) { + (result as Partial)[property] = false as never; + } } - } else { - excludedFolder = undefined; } + return result; +} + +function applyWhitelistOverrides( + excluded: Partial, + whitelisted: WhitelistedFolder | WhitelistedPattern, +): Partial { + const out: Partial = { ...excluded }; + if (out.disableAutoCreate !== undefined) { + out.disableAutoCreate = !whitelisted.enableAutoCreate; + } + if (out.disableFolderNote !== undefined) { + out.disableFolderNote = !whitelisted.enableFolderNote; + } + if (out.disableSync !== undefined) { + out.disableSync = !whitelisted.enableSync; + } + out.enableCollapsing = !whitelisted.disableCollapsing; + if (out.excludeFromFolderOverview !== undefined) { + out.excludeFromFolderOverview = !whitelisted.showInFolderOverview; + } + out.showFolderNote = !whitelisted.hideInFileExplorer; + return out; +} - if (excludedFolder?.detached) { ignoreWhitelist = true; } - - if (whitelistedFolder && excludedFolder && !ignoreWhitelist) { - excludedFolder.disableAutoCreate ? excludedFolder.disableAutoCreate = !whitelistedFolder.enableAutoCreate : ''; - excludedFolder.disableFolderNote ? excludedFolder.disableFolderNote = !whitelistedFolder.enableFolderNote : ''; - excludedFolder.disableSync ? excludedFolder.disableSync = !whitelistedFolder.enableSync : ''; - excludedFolder.enableCollapsing = !whitelistedFolder.disableCollapsing; - excludedFolder.excludeFromFolderOverview ? excludedFolder.excludeFromFolderOverview = !whitelistedFolder.showInFolderOverview : ''; - excludedFolder.showFolderNote = !whitelistedFolder.hideInFileExplorer; - } else if (excludedFolder && Object.keys(excludedFolder).length === 0) { - excludedFolder = { +function defaultExcludedIfEmpty( + value: Partial | undefined, +): ExcludedFolder | undefined { + if (value && Object.keys(value).length === 0) { + return { type: 'folder', id: '', path: '', @@ -77,23 +101,54 @@ export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, inclu showFolderNote: false, }; } + return value as ExcludedFolder | undefined; +} + +export function getExcludedFolder( + plugin: FolderNotesPlugin, + path: string, + includeDetached: boolean, + pathOnly?: boolean, + ignoreWhitelist?: boolean, +): ExcludedFolder | ExcludePattern | undefined { + const combined = combineExcluded(plugin, path, includeDetached, pathOnly); + let excluded = aggregateFlags(combined); + + const whitelist = getWhitelistedFolder( + plugin, + path, + ) as WhitelistedFolder | WhitelistedPattern | undefined; - return excludedFolder; + let skipWhitelist = ignoreWhitelist ?? false; + if (excluded?.detached) skipWhitelist = true; + + if (whitelist && excluded && !skipWhitelist) { + excluded = applyWhitelistOverrides(excluded, whitelist); + } + + return defaultExcludedIfEmpty(excluded) as ExcludedFolder | ExcludePattern | undefined; } -export function getDetachedFolder(plugin: FolderNotesPlugin, path: string) { +export function getDetachedFolder( + plugin: FolderNotesPlugin, + path: string, +): ExcludedFolder | undefined { return plugin.settings.excludeFolders.find((f) => f.path === path && f.detached); } - -export function getExcludedFolderByPath(plugin: FolderNotesPlugin, path: string) { +export function getExcludedFolderByPath( + plugin: FolderNotesPlugin, + path: string, +): ExcludedFolder | undefined { return plugin.settings.excludeFolders.find((excludedFolder) => { if (path.trim() === '' || !excludedFolder.path) { return false; } if (excludedFolder.path === path) { return true; } if (!excludedFolder.subFolders) { return false; } - const excludedFolderPath = excludedFolder.path.includes('/') ? excludedFolder.path : excludedFolder.path + '/'; + const excludedFolderPath = excludedFolder.path.includes('/') + ? excludedFolder.path + : `${excludedFolder.path}/`; let folderPath = getFolderPathFromString(path); - folderPath = folderPath.includes('/') ? folderPath : folderPath + '/'; + folderPath = folderPath.includes('/') ? folderPath : `${folderPath}/`; if (folderPath.includes('/') || folderPath.includes('\\')) { return folderPath.startsWith(excludedFolderPath) || folderPath === excludedFolderPath; @@ -103,14 +158,19 @@ export function getExcludedFolderByPath(plugin: FolderNotesPlugin, path: string) }); } -export function getExcludedFoldersByPath(plugin: FolderNotesPlugin, path: string) { +export function getExcludedFoldersByPath( + plugin: FolderNotesPlugin, + path: string, +): ExcludedFolder[] { return plugin.settings.excludeFolders.filter((excludedFolder) => { if (path.trim() === '' || !excludedFolder.path) { return false; } if (excludedFolder.path === path) { return true; } if (!excludedFolder.subFolders) { return false; } - const excludedFolderPath = excludedFolder.path.includes('/') ? excludedFolder.path : excludedFolder.path + '/'; + const excludedFolderPath = excludedFolder.path.includes('/') + ? excludedFolder.path + : `${excludedFolder.path}/`; let folderPath = getFolderPathFromString(path); - folderPath = folderPath.includes('/') ? folderPath : folderPath + '/'; + folderPath = folderPath.includes('/') ? folderPath : `${folderPath}/`; if (folderPath.includes('/') || folderPath.includes('\\')) { return folderPath.startsWith(excludedFolderPath) || folderPath === excludedFolderPath; @@ -120,32 +180,52 @@ export function getExcludedFoldersByPath(plugin: FolderNotesPlugin, path: string }); } -export function addExcludedFolder(plugin: FolderNotesPlugin, excludedFolder: ExcludedFolder, reloadStyles = true) { +export function addExcludedFolder( + plugin: FolderNotesPlugin, + excludedFolder: ExcludedFolder, + reloadStyles = true, +): void { plugin.settings.excludeFolders.push(excludedFolder); - plugin.saveSettings(reloadStyles); + void plugin.saveSettings(reloadStyles); } -export async function deleteExcludedFolder(plugin: FolderNotesPlugin, excludedFolder: ExcludedFolder) { - plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== excludedFolder.id || folder.type === 'pattern'); - plugin.saveSettings(true); +export async function deleteExcludedFolder( + plugin: FolderNotesPlugin, + excludedFolder: ExcludedFolder, +): Promise { + plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter( + (folder) => folder.id !== excludedFolder.id || folder.type === 'pattern', + ); + await plugin.saveSettings(true); resyncArray(plugin); } -export function updateExcludedFolder(plugin: FolderNotesPlugin, excludedFolder: ExcludePattern, newExcludeFolder: ExcludePattern) { - plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== excludedFolder.id); +export function updateExcludedFolder( + plugin: FolderNotesPlugin, + excludedFolder: ExcludePattern, + newExcludeFolder: ExcludePattern, +): void { + plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter( + (folder) => folder.id !== excludedFolder.id, + ); addExcludedFolder(plugin, newExcludeFolder); } -export function resyncArray(plugin: FolderNotesPlugin) { - plugin.settings.excludeFolders = plugin.settings.excludeFolders.sort((a, b) => a.position - b.position); +export function resyncArray(plugin: FolderNotesPlugin): void { + plugin.settings.excludeFolders = plugin.settings.excludeFolders.sort( + (a, b) => a.position - b.position, + ); plugin.settings.excludeFolders.forEach((folder, index) => { folder.position = index; }); - plugin.saveSettings(); + void plugin.saveSettings(); } - -export function addExcludeFolderListItem(settings: SettingsTab, containerEl: HTMLElement, excludedFolder: ExcludedFolder) { +export function addExcludeFolderListItem( + settings: SettingsTab, + containerEl: HTMLElement, + excludedFolder: ExcludedFolder, +): void { const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); @@ -155,14 +235,19 @@ export function addExcludeFolderListItem(settings: SettingsTab, containerEl: HTM plugin, false, ); - // @ts-ignore + // @ts-expect-error Obsidian's public types don't include this property cb.containerEl.addClass('fn-exclude-folder-path'); cb.setPlaceholder('Folder path'); cb.setValue(excludedFolder.path || ''); cb.onChange((value) => { if (value.startsWith('{regex}') || value.includes('*')) { deleteExcludedFolder(plugin, excludedFolder); - const pattern = new ExcludePattern(value, plugin.settings.excludeFolders.length, undefined, plugin); + const pattern = new ExcludePattern( + value, + plugin.settings.excludeFolders.length, + undefined, + plugin, + ); addExcludedFolder(plugin, pattern); addExcludePatternListItem(settings, containerEl, pattern); setting.clear(); @@ -190,7 +275,9 @@ export function addExcludeFolderListItem(settings: SettingsTab, containerEl: HTM if (excludedFolder.position === 0) { return; } excludedFolder.position -= 1; updateExcludedFolder(plugin, excludedFolder, excludedFolder); - const oldExcludedFolder = plugin.settings.excludeFolders.find((folder) => folder.position === excludedFolder.position); + const oldExcludedFolder = plugin.settings.excludeFolders.find( + (folder) => folder.position === excludedFolder.position, + ); if (oldExcludedFolder) { oldExcludedFolder.position += 1; if (oldExcludedFolder.type === 'pattern') { @@ -213,7 +300,9 @@ export function addExcludeFolderListItem(settings: SettingsTab, containerEl: HTM excludedFolder.position += 1; updateExcludedFolder(plugin, excludedFolder, excludedFolder); - const oldExcludedFolder = plugin.settings.excludeFolders.find((folder) => folder.position === excludedFolder.position); + const oldExcludedFolder = plugin.settings.excludeFolders.find( + (folder) => folder.position === excludedFolder.position, + ); if (oldExcludedFolder) { oldExcludedFolder.position -= 1; if (oldExcludedFolder.type === 'pattern') { diff --git a/src/ExcludeFolders/functions/patternFunctions.ts b/src/ExcludeFolders/functions/patternFunctions.ts index 8e4e4ae..db69acf 100644 --- a/src/ExcludeFolders/functions/patternFunctions.ts +++ b/src/ExcludeFolders/functions/patternFunctions.ts @@ -5,79 +5,97 @@ import type { SettingsTab } from '../../settings/SettingsTab'; import { addExcludedFolder, resyncArray, updateExcludedFolder } from './folderFunctions'; import PatternSettings from '../modals/PatternSettings'; -export function updatePattern(plugin: FolderNotesPlugin, pattern: ExcludePattern, newPattern: ExcludePattern) { - plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== pattern.id); +const REGEX_PREFIX = '{regex}'; +const STAR = '*'; +const INDEX_START = 0; +const SLICE_START_ONE = 1; +const SLICE_EXCLUDE_LAST = -1; + +function matchesPatternSpec(raw: string | undefined, folderName: string): boolean { + if (!raw) return false; + const string = raw.trim(); + const isRegex = string.startsWith(REGEX_PREFIX); + const hasStartStar = string.startsWith(STAR); + const hasEndStar = string.endsWith(STAR); + if (!isRegex && !(hasStartStar || hasEndStar)) return false; + + if (isRegex) { + const body = string.replace(REGEX_PREFIX, '').trim(); + if (body === '') return false; + try { + return new RegExp(body).test(folderName); + } catch { + return false; + } + } + + if (hasStartStar && hasEndStar) { + const inner = string.slice(SLICE_START_ONE, SLICE_EXCLUDE_LAST); + return folderName.includes(inner); + } + if (hasStartStar) { + const suffix = string.slice(SLICE_START_ONE); + return folderName.endsWith(suffix); + } + if (hasEndStar) { + const prefix = string.slice(INDEX_START, SLICE_EXCLUDE_LAST); + return folderName.startsWith(prefix); + } + return false; +} + +export function updatePattern( + plugin: FolderNotesPlugin, + pattern: ExcludePattern, + newPattern: ExcludePattern, +): void { + plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter( + (folder) => folder.id !== pattern.id, + ); addExcludedFolder(plugin, newPattern); } -export function deletePattern(plugin: FolderNotesPlugin, pattern: ExcludePattern) { - plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== pattern.id || folder.type === 'folder'); - plugin.saveSettings(true); +export async function deletePattern( + plugin: FolderNotesPlugin, + pattern: ExcludePattern, +): Promise { + plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter( + (folder) => folder.id !== pattern.id || folder.type === 'folder', + ); + await plugin.saveSettings(true); resyncArray(plugin); } -export function getExcludedFoldersByPattern(plugin: FolderNotesPlugin, folderName: string): ExcludePattern[] { - return plugin.settings.excludeFolders.filter((s) => s.type === 'pattern').filter((pattern) => { - if (!pattern.string) { return false; } - const string = pattern.string.trim(); - if (!string.startsWith('{regex}') && !(string.startsWith('*') || string.endsWith('*'))) { return false; } - const regex = string.replace('{regex}', '').trim(); - if (string.startsWith('{regex}') && regex === '') { return false; } - if (regex !== undefined && string.startsWith('{regex}')) { - const match = new RegExp(regex).exec(folderName); - if (match) { - return true; - } - } else if (string.startsWith('*') && string.endsWith('*')) { - if (folderName.includes(string.slice(1, -1))) { - return true; - } - } else if (string.startsWith('*')) { - if (folderName.endsWith(string.slice(1))) { - return true; - } - } else if (string.endsWith('*')) { - if (folderName.startsWith(string.slice(0, -1))) { - return true; - } - } - }); +export function getExcludedFoldersByPattern( + plugin: FolderNotesPlugin, + folderName: string, +): ExcludePattern[] { + return plugin.settings.excludeFolders + .filter((s) => s.type === 'pattern') + .filter((pattern) => matchesPatternSpec(pattern.string, folderName)) as ExcludePattern[]; } -export function getExcludedFolderByPattern(plugin: FolderNotesPlugin, folderName: string): ExcludePattern | undefined{ - return plugin.settings.excludeFolders.filter((s) => s.type === 'pattern').find((pattern) => { - if (!pattern.string) { return false; } - const string = pattern.string.trim(); - if (!string.startsWith('{regex}') && !(string.startsWith('*') || string.endsWith('*'))) { return false; } - const regex = string.replace('{regex}', '').trim(); - if (string.startsWith('{regex}') && regex === '') { return false; } - if (regex !== undefined && string.startsWith('{regex}')) { - const match = new RegExp(regex).exec(folderName); - if (match) { - return true; - } - } else if (string.startsWith('*') && string.endsWith('*')) { - if (folderName.includes(string.slice(1, -1))) { - return true; - } - } else if (string.startsWith('*')) { - if (folderName.endsWith(string.slice(1))) { - return true; - } - } else if (string.endsWith('*')) { - if (folderName.startsWith(string.slice(0, -1))) { - return true; - } - } - }); +export function getExcludedFolderByPattern( + plugin: FolderNotesPlugin, + folderName: string, +): ExcludePattern | undefined { + return ( + plugin.settings.excludeFolders + .filter((s) => s.type === 'pattern') + .find((pattern) => matchesPatternSpec(pattern.string, folderName)) + ) as ExcludePattern | undefined; } -export function addExcludePatternListItem(settings: SettingsTab, containerEl: HTMLElement, pattern: ExcludePattern) { +export function addExcludePatternListItem( + settings: SettingsTab, + containerEl: HTMLElement, + pattern: ExcludePattern, +): void { const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); setting.addSearch((cb) => { - // @ts-ignore + // @ts-expect-error Obsidian's public types don't include containerEl on this control cb.containerEl.addClass('fn-exclude-folder-path'); cb.setPlaceholder('Pattern'); cb.setValue(pattern.string); @@ -102,11 +120,18 @@ export function addExcludePatternListItem(settings: SettingsTab, containerEl: HT if (pattern.position === 0) { return; } pattern.position -= 1; updatePattern(plugin, pattern, pattern); - const oldPattern = plugin.settings.excludeFolders.find((folder) => folder.position === pattern.position); + const oldPattern = plugin.settings.excludeFolders.find( + (folder) => folder.position === pattern.position, + ); if (oldPattern) { oldPattern.position += 1; if (oldPattern.type === 'pattern') { - updatePattern(plugin, oldPattern, oldPattern); + const pat = oldPattern as ExcludePattern; + updatePattern( + plugin, + pat, + pat, + ); } else { updateExcludedFolder(plugin, oldPattern, oldPattern); } @@ -125,11 +150,18 @@ export function addExcludePatternListItem(settings: SettingsTab, containerEl: HT pattern.position += 1; updatePattern(plugin, pattern, pattern); - const oldPattern = plugin.settings.excludeFolders.find((folder) => folder.position === pattern.position); + const oldPattern = plugin.settings.excludeFolders.find( + (folder) => folder.position === pattern.position, + ); if (oldPattern) { oldPattern.position -= 1; if (oldPattern.type === 'pattern') { - updatePattern(plugin, oldPattern, oldPattern); + const pat = oldPattern as ExcludePattern; + updatePattern( + plugin, + pat, + pat, + ); } else { updateExcludedFolder(plugin, oldPattern, oldPattern); } @@ -143,7 +175,7 @@ export function addExcludePatternListItem(settings: SettingsTab, containerEl: HT cb.setIcon('trash-2'); cb.setTooltip('Delete pattern'); cb.onClick(() => { - deletePattern(plugin, pattern); + void deletePattern(plugin, pattern); setting.clear(); setting.settingEl.remove(); }); diff --git a/src/ExcludeFolders/functions/whitelistFolderFunctions.ts b/src/ExcludeFolders/functions/whitelistFolderFunctions.ts index 156a716..e700eac 100644 --- a/src/ExcludeFolders/functions/whitelistFolderFunctions.ts +++ b/src/ExcludeFolders/functions/whitelistFolderFunctions.ts @@ -2,15 +2,21 @@ import type FolderNotesPlugin from '../../main'; import { getFolderNameFromPathString, getFolderPathFromString } from '../../functions/utils'; import type { WhitelistedFolder } from '../WhitelistFolder'; import { WhitelistedPattern } from '../WhitelistPattern'; -import { Setting, Platform, ButtonComponent } from 'obsidian'; +import { Setting, ButtonComponent } from 'obsidian'; import { FolderSuggest } from '../../suggesters/FolderSuggester'; import type { SettingsTab } from '../../settings/SettingsTab'; import WhitelistFolderSettings from '../modals/WhitelistFolderSettings'; -import { updateWhitelistedPattern, getWhitelistedFoldersByPattern, addWhitelistedPatternListItem } from './whitelistPatternFunctions'; -Platform.isMobileApp; - -export function getWhitelistedFolder(plugin: FolderNotesPlugin, path: string) { - let whitelistedFolder = {} as WhitelistedFolder | WhitelistedPattern | undefined; +import { + updateWhitelistedPattern, + getWhitelistedFoldersByPattern, + addWhitelistedPatternListItem, +} from './whitelistPatternFunctions'; + +export function getWhitelistedFolder( + plugin: FolderNotesPlugin, + path: string, +): WhitelistedFolder | WhitelistedPattern | undefined { + let whitelistedFolder: Partial | undefined = {}; const folderName = getFolderNameFromPathString(path); const matchedPatterns = getWhitelistedFoldersByPattern(plugin, folderName); const whitelistedFolders = getWhitelistedFoldersByPath(plugin, path); @@ -25,21 +31,30 @@ export function getWhitelistedFolder(plugin: FolderNotesPlugin, path: string) { if (combinedWhitelistedFolders.length > 0) { for (const matchedFolder of combinedWhitelistedFolders) { propertiesToCopy.forEach((property) => { - if (matchedFolder[property] === true) { - (whitelistedFolder as any)[property] = true; - } else if (!matchedFolder[property]) { - (whitelistedFolder as any)[property] = false; + const value = (matchedFolder as Partial)[property]; + if (value === true) { + (whitelistedFolder as Partial)[property] = true as never; + } else if (!value) { + (whitelistedFolder as Partial)[property] = false as never; } }); } } - if ((whitelistedFolder instanceof Object) && Object.keys(whitelistedFolder).length === 0) { whitelistedFolder = undefined; } + if ( + whitelistedFolder + && Object.keys(whitelistedFolder).length === 0 + ) { + whitelistedFolder = undefined; + } - return whitelistedFolder; + return whitelistedFolder as WhitelistedFolder | WhitelistedPattern | undefined; } -export function getWhitelistedFolderByPath(plugin: FolderNotesPlugin, path: string) { +export function getWhitelistedFolderByPath( + plugin: FolderNotesPlugin, + path: string, +): WhitelistedFolder | WhitelistedPattern | undefined { return plugin.settings.whitelistFolders.find((whitelistedFolder) => { if (whitelistedFolder.path === path) { return true; } if (!whitelistedFolder.subFolders) { return false; } @@ -47,7 +62,10 @@ export function getWhitelistedFolderByPath(plugin: FolderNotesPlugin, path: stri }); } -export function getWhitelistedFoldersByPath(plugin: FolderNotesPlugin, path: string) { +export function getWhitelistedFoldersByPath( + plugin: FolderNotesPlugin, + path: string, +): Array { return plugin.settings.whitelistFolders.filter((whitelistedFolder) => { if (whitelistedFolder.path === path) { return true; } if (!whitelistedFolder.subFolders) { return false; } @@ -55,37 +73,58 @@ export function getWhitelistedFoldersByPath(plugin: FolderNotesPlugin, path: str }); } -export function addWhitelistedFolder(plugin: FolderNotesPlugin, whitelistedFolder: WhitelistedFolder) { +export function addWhitelistedFolder( + plugin: FolderNotesPlugin, + whitelistedFolder: WhitelistedFolder | WhitelistedPattern, +): void { plugin.settings.whitelistFolders.push(whitelistedFolder); - plugin.saveSettings(true); + void plugin.saveSettings(true); } -export function deleteWhitelistedFolder(plugin: FolderNotesPlugin, whitelistedFolder: WhitelistedFolder) { - plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== whitelistedFolder.id || folder.type === 'pattern'); - plugin.saveSettings(true); +export async function deleteWhitelistedFolder( + plugin: FolderNotesPlugin, + whitelistedFolder: WhitelistedFolder | WhitelistedPattern, +): Promise { + plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter( + (folder) => folder.id !== whitelistedFolder.id || folder.type === 'pattern', + ); + await plugin.saveSettings(true); resyncArray(plugin); } -export function updateWhitelistedFolder(plugin: FolderNotesPlugin, whitelistedFolder: WhitelistedFolder, newWhitelistFolder: WhitelistedFolder) { - plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== whitelistedFolder.id); +export function updateWhitelistedFolder( + plugin: FolderNotesPlugin, + whitelistedFolder: WhitelistedFolder, + newWhitelistFolder: WhitelistedFolder, +): void { + plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter( + (folder) => folder.id !== whitelistedFolder.id, + ); addWhitelistedFolder(plugin, newWhitelistFolder); } -export function resyncArray(plugin: FolderNotesPlugin) { - plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.sort((a, b) => a.position - b.position); +export function resyncArray(plugin: FolderNotesPlugin): void { + plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.sort( + (a, b) => a.position - b.position, + ); plugin.settings.whitelistFolders.forEach((folder, index) => { folder.position = index; }); - plugin.saveSettings(); + void plugin.saveSettings(); } - -export function addWhitelistFolderListItem(settings: SettingsTab, containerEl: HTMLElement, whitelistedFolder: WhitelistedFolder) { +export function addWhitelistFolderListItem( + settings: SettingsTab, + containerEl: HTMLElement, + whitelistedFolder: WhitelistedFolder, +): void { const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); - const inputContainer = setting.settingEl.createDiv({ cls: 'fn-whitelist-folder-input-container' }); + const inputContainer = setting.settingEl.createDiv({ + cls: 'fn-whitelist-folder-input-container', + }); const SearchComponent = new Setting(inputContainer); SearchComponent.addSearch((cb) => { new FolderSuggest( @@ -93,14 +132,19 @@ export function addWhitelistFolderListItem(settings: SettingsTab, containerEl: H plugin, true, ); - // @ts-ignore + // @ts-expect-error Obsidian's public types don't include this property cb.containerEl.addClass('fn-exclude-folder-path'); cb.setPlaceholder('Folder path'); cb.setValue(whitelistedFolder.path); cb.onChange((value) => { if (value.startsWith('{regex}') || value.includes('*')) { - deleteWhitelistedFolder(plugin, whitelistedFolder); - const pattern = new WhitelistedPattern(value, plugin.settings.whitelistFolders.length, undefined, plugin); + void deleteWhitelistedFolder(plugin, whitelistedFolder); + const pattern = new WhitelistedPattern( + value, + plugin.settings.whitelistFolders.length, + undefined, + plugin, + ); addWhitelistedFolder(plugin, pattern); addWhitelistedPatternListItem(settings, containerEl, pattern); setting.clear(); @@ -127,7 +171,9 @@ export function addWhitelistFolderListItem(settings: SettingsTab, containerEl: H if (whitelistedFolder.position === 0) { return; } whitelistedFolder.position -= 1; updateWhitelistedFolder(plugin, whitelistedFolder, whitelistedFolder); - const oldWhitelistedFolder = plugin.settings.whitelistFolders.find((folder) => folder.position === whitelistedFolder.position); + const oldWhitelistedFolder = plugin.settings.whitelistFolders.find( + (folder) => folder.position === whitelistedFolder.position, + ); if (oldWhitelistedFolder) { oldWhitelistedFolder.position += 1; if (oldWhitelistedFolder.type === 'pattern') { @@ -149,7 +195,9 @@ export function addWhitelistFolderListItem(settings: SettingsTab, containerEl: H whitelistedFolder.position += 1; updateWhitelistedFolder(plugin, whitelistedFolder, whitelistedFolder); - const oldWhitelistedFolder = plugin.settings.whitelistFolders.find((folder) => folder.position === whitelistedFolder.position); + const oldWhitelistedFolder = plugin.settings.whitelistFolders.find( + (folder) => folder.position === whitelistedFolder.position, + ); if (oldWhitelistedFolder) { oldWhitelistedFolder.position -= 1; if (oldWhitelistedFolder.type === 'pattern') { @@ -166,7 +214,7 @@ export function addWhitelistFolderListItem(settings: SettingsTab, containerEl: H .setIcon('trash-2') .setTooltip('Delete excluded folder') .onClick(() => { - deleteWhitelistedFolder(plugin, whitelistedFolder); + void deleteWhitelistedFolder(plugin, whitelistedFolder); setting.clear(); setting.settingEl.remove(); }); diff --git a/src/ExcludeFolders/functions/whitelistPatternFunctions.ts b/src/ExcludeFolders/functions/whitelistPatternFunctions.ts index 30f5363..6c50e68 100644 --- a/src/ExcludeFolders/functions/whitelistPatternFunctions.ts +++ b/src/ExcludeFolders/functions/whitelistPatternFunctions.ts @@ -6,84 +6,106 @@ import WhitelistPatternSettings from '../modals/WhitelistPatternSettings'; import type { WhitelistedPattern } from '../WhitelistPattern'; import { addWhitelistedFolder, updateWhitelistedFolder } from './whitelistFolderFunctions'; -export function updateWhitelistedPattern(plugin: FolderNotesPlugin, pattern: WhitelistedPattern, newPattern: WhitelistedPattern) { - plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== pattern.id); +const REGEX_PREFIX = '{regex}'; +const STAR = '*'; +const SLICE_START_ONE = 1; +const SLICE_EXCLUDE_LAST = -1; + +function matchesPatternSpec(raw: string | undefined, folderName: string): boolean { + if (!raw) return false; + const string = raw.trim(); + const isRegex = string.startsWith(REGEX_PREFIX); + const hasStartStar = string.startsWith(STAR); + const hasEndStar = string.endsWith(STAR); + if (!isRegex && !(hasStartStar || hasEndStar)) return false; + + if (isRegex) { + const body = string.replace(REGEX_PREFIX, '').trim(); + if (body === '') return false; + try { + return new RegExp(body).test(folderName); + } catch { + return false; + } + } + + if (hasStartStar && hasEndStar) { + const inner = string.slice(SLICE_START_ONE, SLICE_EXCLUDE_LAST); + return folderName.includes(inner); + } + if (hasStartStar) { + const suffix = string.slice(SLICE_START_ONE); + return folderName.endsWith(suffix); + } + if (hasEndStar) { + const prefix = string.slice(0, SLICE_EXCLUDE_LAST); + return folderName.startsWith(prefix); + } + return false; +} + +export function updateWhitelistedPattern( + plugin: FolderNotesPlugin, + pattern: WhitelistedPattern, + newPattern: WhitelistedPattern, +): void { + plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter( + (folder) => folder.id !== pattern.id, + ); addWhitelistedFolder(plugin, newPattern); } -export function deletePattern(plugin: FolderNotesPlugin, pattern: WhitelistedPattern) { - plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter((folder) => folder.id !== pattern.id || folder.type === 'folder'); - plugin.saveSettings(true); +export async function deletePattern( + plugin: FolderNotesPlugin, + pattern: WhitelistedPattern, +): Promise { + plugin.settings.whitelistFolders = plugin.settings.whitelistFolders.filter( + (folder) => folder.id !== pattern.id || folder.type === 'folder', + ); + await plugin.saveSettings(true); resyncArray(plugin); } -export function getWhitelistedFolderByPattern(plugin: FolderNotesPlugin, folderName: string) { - return plugin.settings.whitelistFolders.filter((s) => s.type === 'pattern').find((pattern) => { - if (!pattern.string) { return false; } - const string = pattern.string.trim(); - if (!string.startsWith('{regex}') && !(string.startsWith('*') || string.endsWith('*'))) { return false; } - const regex = string.replace('{regex}', '').trim(); - if (string.startsWith('{regex}') && regex === '') { return false; } - if (regex !== undefined && string.startsWith('{regex}')) { - const match = new RegExp(regex).exec(folderName); - if (match) { - return true; - } - } else if (string.startsWith('*') && string.endsWith('*')) { - if (folderName.includes(string.slice(1, -1))) { - return true; - } - } else if (string.startsWith('*')) { - if (folderName.endsWith(string.slice(1))) { - return true; - } - } else if (string.endsWith('*')) { - if (folderName.startsWith(string.slice(0, -1))) { - return true; - } - } - }); +export function getWhitelistedFolderByPattern( + plugin: FolderNotesPlugin, + folderName: string, +): WhitelistedPattern | undefined { + return ( + plugin.settings.whitelistFolders + .filter((s) => s.type === 'pattern') + .find((pattern) => matchesPatternSpec(pattern.string, folderName)) + ) as WhitelistedPattern | undefined; } -export function getWhitelistedFoldersByPattern(plugin: FolderNotesPlugin, folderName: string) { - return plugin.settings.whitelistFolders.filter((s) => s.type === 'pattern').filter((pattern) => { - if (!pattern.string) { return false; } - const string = pattern.string.trim(); - if (!string.startsWith('{regex}') && !(string.startsWith('*') || string.endsWith('*'))) { return false; } - const regex = string.replace('{regex}', '').trim(); - if (string.startsWith('{regex}') && regex === '') { return false; } - if (regex !== undefined && string.startsWith('{regex}')) { - const match = new RegExp(regex).exec(folderName); - if (match) { - return true; - } - } else if (string.startsWith('*') && string.endsWith('*')) { - if (folderName.includes(string.slice(1, -1))) { - return true; - } - } else if (string.startsWith('*')) { - if (folderName.endsWith(string.slice(1))) { - return true; - } - } else if (string.endsWith('*')) { - if (folderName.startsWith(string.slice(0, -1))) { - return true; - } - } - }); +export function getWhitelistedFoldersByPattern( + plugin: FolderNotesPlugin, + folderName: string, +): WhitelistedPattern[] { + return ( + plugin.settings.whitelistFolders + .filter((s) => s.type === 'pattern') + .filter((pattern) => matchesPatternSpec(pattern.string, folderName)) + ) as WhitelistedPattern[]; } -export function addWhitelistedPatternListItem(settings: SettingsTab, containerEl: HTMLElement, pattern: WhitelistedPattern) { +export function addWhitelistedPatternListItem( + settings: SettingsTab, + containerEl: HTMLElement, + pattern: WhitelistedPattern, +): void { const { plugin } = settings; const setting = new Setting(containerEl); setting.setClass('fn-exclude-folder-list'); setting.addSearch((cb) => { - // @ts-ignore + // @ts-expect-error Obsidian's public types don't expose containerEl on this control cb.containerEl.addClass('fn-exclude-folder-path'); cb.setPlaceholder('Pattern'); cb.setValue(pattern.string); cb.onChange((value) => { - if (plugin.settings.whitelistFolders.find((folder) => folder.string === value)) { return; } + const exists = plugin.settings.whitelistFolders.some( + (folder) => folder.string === value, + ); + if (exists) { return; } pattern.string = value; updateWhitelistedPattern(plugin, pattern, pattern); }); @@ -103,11 +125,17 @@ export function addWhitelistedPatternListItem(settings: SettingsTab, containerEl if (pattern.position === 0) { return; } pattern.position -= 1; updateWhitelistedPattern(plugin, pattern, pattern); - const oldPattern = plugin.settings.whitelistFolders.find((folder) => folder.position === pattern.position); + const oldPattern = plugin.settings.whitelistFolders.find( + (folder) => folder.position === pattern.position, + ); if (oldPattern) { oldPattern.position += 1; if (oldPattern.type === 'pattern') { - updateWhitelistedPattern(plugin, oldPattern, oldPattern); + updateWhitelistedPattern( + plugin, + oldPattern as WhitelistedPattern, + oldPattern as WhitelistedPattern, + ); } else { updateWhitelistedFolder(plugin, oldPattern, oldPattern); } @@ -126,11 +154,17 @@ export function addWhitelistedPatternListItem(settings: SettingsTab, containerEl pattern.position += 1; updateWhitelistedPattern(plugin, pattern, pattern); - const oldPattern = plugin.settings.whitelistFolders.find((folder) => folder.position === pattern.position); + const oldPattern = plugin.settings.whitelistFolders.find( + (folder) => folder.position === pattern.position, + ); if (oldPattern) { oldPattern.position -= 1; if (oldPattern.type === 'pattern') { - updateWhitelistedPattern(plugin, oldPattern, oldPattern); + updateWhitelistedPattern( + plugin, + oldPattern as WhitelistedPattern, + oldPattern as WhitelistedPattern, + ); } else { updateWhitelistedFolder(plugin, oldPattern, oldPattern); } @@ -143,7 +177,7 @@ export function addWhitelistedPatternListItem(settings: SettingsTab, containerEl cb.setIcon('trash-2'); cb.setTooltip('Delete pattern'); cb.onClick(() => { - deletePattern(plugin, pattern); + void deletePattern(plugin, pattern); setting.clear(); setting.settingEl.remove(); }); diff --git a/src/ExcludeFolders/modals/ExcludeFolderSettings.ts b/src/ExcludeFolders/modals/ExcludeFolderSettings.ts index 7f634b2..7537889 100644 --- a/src/ExcludeFolders/modals/ExcludeFolderSettings.ts +++ b/src/ExcludeFolders/modals/ExcludeFolderSettings.ts @@ -1,5 +1,4 @@ -import type { App } from 'obsidian'; -import { Modal, Setting } from 'obsidian'; +import { Modal, Setting, type App } from 'obsidian'; import type FolderNotesPlugin from '../../main'; import type { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; import { updateCSSClassesForFolder } from 'src/functions/styleFunctions'; @@ -13,10 +12,10 @@ export default class ExcludedFolderSettings extends Modal { this.app = app; this.excludedFolder = excludedFolder; } - onOpen() { + onOpen(): void { this.display(); } - display() { + display(): void { const { contentEl } = this; contentEl.empty(); contentEl.createEl('h2', { text: 'Excluded folder settings' }); @@ -108,9 +107,9 @@ export default class ExcludedFolderSettings extends Modal { }), ); } - } - onClose() { + + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/ExcludeFolders/modals/PatternSettings.ts b/src/ExcludeFolders/modals/PatternSettings.ts index 426f228..49d53c5 100644 --- a/src/ExcludeFolders/modals/PatternSettings.ts +++ b/src/ExcludeFolders/modals/PatternSettings.ts @@ -1,5 +1,4 @@ -import type { App } from 'obsidian'; -import { Modal, Setting } from 'obsidian'; +import { Modal, Setting, type App } from 'obsidian'; import type FolderNotesPlugin from '../../main'; import type { ExcludePattern } from 'src/ExcludeFolders/ExcludePattern'; import { refreshAllFolderStyles } from 'src/functions/styleFunctions'; @@ -14,16 +13,19 @@ export default class PatternSettings extends Modal { this.app = app; this.pattern = pattern; } - onOpen() { + + onOpen(): void { this.display(); } - display() { + + display(): void { const { contentEl } = this; contentEl.empty(); contentEl.createEl('h2', { text: 'Pattern settings' }); new Setting(contentEl) .setName('Disable folder name sync') + // eslint-disable-next-line max-len .setDesc('Choose if the folder name should be renamed when the file name has been changed') .addToggle((toggle) => toggle @@ -36,6 +38,7 @@ export default class PatternSettings extends Modal { new Setting(contentEl) .setName('Disable auto creation of folder notes in this folder') + // eslint-disable-next-line max-len .setDesc('Choose if a folder note should be created when a new folder is created that matches this pattern') .addToggle((toggle) => toggle @@ -98,9 +101,9 @@ export default class PatternSettings extends Modal { }), ); } - } - onClose() { + + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/ExcludeFolders/modals/WhitelistFolderSettings.ts b/src/ExcludeFolders/modals/WhitelistFolderSettings.ts index 6f65cc7..f7e0c76 100644 --- a/src/ExcludeFolders/modals/WhitelistFolderSettings.ts +++ b/src/ExcludeFolders/modals/WhitelistFolderSettings.ts @@ -1,5 +1,4 @@ -import type { App } from 'obsidian'; -import { Modal, Setting } from 'obsidian'; +import { Modal, Setting, type App } from 'obsidian'; import type FolderNotesPlugin from '../../main'; import type { WhitelistedFolder } from '../WhitelistFolder'; export default class WhitelistFolderSettings extends Modal { @@ -12,10 +11,12 @@ export default class WhitelistFolderSettings extends Modal { this.app = app; this.whitelistedFolder = whitelistedFolder; } - onOpen() { + + onOpen(): void { this.display(); } - display() { + + display(): void { const { contentEl } = this; contentEl.empty(); contentEl.createEl('h2', { text: 'Whitelisted folder settings' }); @@ -33,6 +34,7 @@ export default class WhitelistFolderSettings extends Modal { new Setting(contentEl) .setName('Enable folder name sync') + // eslint-disable-next-line max-len .setDesc('Choose if the name of a folder note should be renamed when the folder name is changed') .addToggle((toggle) => toggle @@ -107,7 +109,7 @@ export default class WhitelistFolderSettings extends Modal { } } - onClose() { + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/ExcludeFolders/modals/WhitelistPatternSettings.ts b/src/ExcludeFolders/modals/WhitelistPatternSettings.ts index 45a3688..4f62f29 100644 --- a/src/ExcludeFolders/modals/WhitelistPatternSettings.ts +++ b/src/ExcludeFolders/modals/WhitelistPatternSettings.ts @@ -1,5 +1,4 @@ -import type { App } from 'obsidian'; -import { Modal, Setting } from 'obsidian'; +import { Modal, Setting, type App } from 'obsidian'; import type FolderNotesPlugin from '../../main'; import type { WhitelistedPattern } from '../WhitelistPattern'; @@ -13,15 +12,18 @@ export default class WhitelistPatternSettings extends Modal { this.app = app; this.pattern = pattern; } - onOpen() { + + onOpen(): void { this.display(); } - display() { + + display(): void { const { contentEl } = this; contentEl.empty(); contentEl.createEl('h2', { text: 'Whitelisted pattern settings' }); new Setting(contentEl) .setName('Enable folder name sync') + // eslint-disable-next-line max-len .setDesc('Choose if the name of a folder note should be renamed when the folder name is changed') .addToggle((toggle) => toggle @@ -82,9 +84,9 @@ export default class WhitelistPatternSettings extends Modal { }), ); } - } - onClose() { + + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts b/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts index 2321f34..b00342d 100644 --- a/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts +++ b/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts @@ -1,9 +1,11 @@ -import type { App } from 'obsidian'; -import { Modal, Setting } from 'obsidian'; +import { Modal, Setting, type App } from 'obsidian'; import type { SettingsTab } from 'src/settings/SettingsTab'; import type FolderNotesPlugin from '../../main'; import { WhitelistedFolder } from '../WhitelistFolder'; -import { addWhitelistFolderListItem, addWhitelistedFolder } from '../functions/whitelistFolderFunctions'; +import { + addWhitelistFolderListItem, + addWhitelistedFolder, +} from '../functions/whitelistFolderFunctions'; import { addWhitelistedPatternListItem } from '../functions/whitelistPatternFunctions'; export default class WhitelistedFoldersSettings extends Modal { @@ -16,7 +18,8 @@ export default class WhitelistedFoldersSettings extends Modal { this.settingsTab = settingsTab; this.app = settingsTab.app; } - onOpen() { + + onOpen(): void { const { contentEl } = this; contentEl.createEl('h2', { text: 'Manage whitelisted folders' }); @@ -29,22 +32,31 @@ export default class WhitelistedFoldersSettings extends Modal { cb.setClass('add-exclude-folder'); cb.setTooltip('Add whitelisted folder'); cb.onClick(() => { - const whitelistedFolder = new WhitelistedFolder('', this.plugin.settings.whitelistFolders.length, undefined, this.plugin); - addWhitelistFolderListItem(this.plugin.settingsTab, contentEl, whitelistedFolder); + const whitelistedFolder = new WhitelistedFolder( + '', this.plugin.settings.whitelistFolders.length, + undefined, this.plugin, + ); + addWhitelistFolderListItem( + this.plugin.settingsTab, contentEl, whitelistedFolder, + ); addWhitelistedFolder(this.plugin, whitelistedFolder); this.settingsTab.display(); }); }); - this.plugin.settings.whitelistFolders.sort((a, b) => a.position - b.position).forEach((whitelistedFolder) => { - if (whitelistedFolder.string?.trim() !== '' && whitelistedFolder.path?.trim() === '') { - addWhitelistedPatternListItem(this.settingsTab, contentEl, whitelistedFolder); - } else { - addWhitelistFolderListItem(this.settingsTab, contentEl, whitelistedFolder); - } - }); + + this.plugin.settings.whitelistFolders + .sort((a, b) => a.position - b.position) + .forEach((whitelistedFolder) => { + if (whitelistedFolder.string?.trim() !== '' && + whitelistedFolder.path?.trim() === '') { + addWhitelistedPatternListItem(this.settingsTab, contentEl, whitelistedFolder); + } else { + addWhitelistFolderListItem(this.settingsTab, contentEl, whitelistedFolder); + } + }); } - onClose() { + onClose(): void { const { contentEl } = this; contentEl.empty(); } From 7c31c7cec57ebd1aefdb69f0e365674abc134138 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:39:33 +0200 Subject: [PATCH 25/47] Every remaining file --- src/Commands.ts | 470 ++++++++++-------- src/functions/ListComponent.ts | 26 +- src/functions/excalidraw.ts | 33 +- src/functions/folderNoteFunctions.ts | 454 ++++++++++++----- src/functions/styleFunctions.ts | 83 +++- src/functions/utils.ts | 23 +- src/globals.d.ts | 2 - src/main.ts | 292 +++++++---- src/modals/AddSupportedFileType.ts | 12 +- src/modals/AskForExtension.ts | 27 +- src/modals/DeleteConfirmation.ts | 28 +- src/modals/ExistingNote.ts | 29 +- src/modals/FolderName.ts | 23 +- src/modals/NewFolderName.ts | 27 +- src/settings/ExcludedFoldersSettings.ts | 49 +- src/settings/FileExplorerSettings.ts | 19 +- src/settings/FolderOverviewSettings.ts | 15 +- src/settings/GeneralSettings.ts | 72 ++- src/settings/PathSettings.ts | 3 +- src/settings/SettingsTab.ts | 49 +- src/settings/modals/BackupWarning.ts | 25 +- src/settings/modals/CreateFnForEveryFolder.ts | 38 +- src/settings/modals/RenameFns.ts | 10 +- src/suggesters/FolderSuggester.ts | 14 +- src/suggesters/Suggest.ts | 17 +- src/suggesters/TemplateSuggester.ts | 18 +- src/template.ts | 66 ++- 27 files changed, 1319 insertions(+), 605 deletions(-) diff --git a/src/Commands.ts b/src/Commands.ts index 56f7dd1..a27b541 100644 --- a/src/Commands.ts +++ b/src/Commands.ts @@ -1,11 +1,35 @@ -import type { App, Menu, TAbstractFile, Editor, MarkdownView } from 'obsidian'; -import { TFolder, Notice, TFile, Platform } from 'obsidian'; +import { + TFolder, + Notice, + TFile, + Platform, + type App, + type Menu, + type TAbstractFile, + type Editor, + type MarkdownView, +} from 'obsidian'; import type FolderNotesPlugin from './main'; -import { getFolderNote, createFolderNote, deleteFolderNote, turnIntoFolderNote, openFolderNote, extractFolderName, detachFolderNote } from './functions/folderNoteFunctions'; +import { + getFolderNote, + createFolderNote, + deleteFolderNote, + turnIntoFolderNote, + openFolderNote, + extractFolderName, + detachFolderNote, +} from './functions/folderNoteFunctions'; import { ExcludedFolder } from './ExcludeFolders/ExcludeFolder'; import { getFolderPathFromString, getFileExplorerActiveFolder } from './functions/utils'; -import { deleteExcludedFolder, getDetachedFolder, getExcludedFolder } from './ExcludeFolders/functions/folderFunctions'; -import { hideFolderNoteInFileExplorer, showFolderNoteInFileExplorer } from './functions/styleFunctions'; +import { + deleteExcludedFolder, + getDetachedFolder, + getExcludedFolder, +} from './ExcludeFolders/functions/folderFunctions'; +import { + hideFolderNoteInFileExplorer, + showFolderNoteInFileExplorer, +} from './functions/styleFunctions'; @@ -16,12 +40,13 @@ export class Commands { this.plugin = plugin; this.app = app; } - registerCommands() { + registerCommands(): void { this.editorCommands(); this.fileCommands(); this.regularCommands(); } - regularCommands() { + + regularCommands(): void { this.plugin.addCommand({ id: 'turn-into-folder-note', name: 'Use this file as the folder note for its parent folder', @@ -52,7 +77,8 @@ export class Commands { if (this.plugin.app.vault.getAbstractFileByPath(newPath)) { return new Notice('Folder already exists'); } - const automaticallyCreateFolderNote = this.plugin.settings.autoCreate; + const automaticallyCreateFolderNote = + this.plugin.settings.autoCreate; this.plugin.settings.autoCreate = false; this.plugin.saveSettings(); await this.plugin.app.vault.createFolder(newPath); @@ -187,6 +213,7 @@ export class Commands { const blacklist = ['*', '\\', '"', '/', '<', '>', '?', '|', ':']; for (const char of blacklist) { if (text.includes(char)) { + // eslint-disable-next-line max-len new Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?'); return false; } @@ -207,13 +234,18 @@ export class Commands { createFolderNote(this.plugin, text, false); } else { - folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + '/' + text); + const folderFullPath = folderPath + '/' + text; + folder = this.plugin.app.vault.getAbstractFileByPath(folderFullPath); if (folder instanceof TFolder) { new Notice('Folder note already exists'); return false; } if (this.plugin.settings.storageLocation === 'parentFolder') { - if (this.app.vault.getAbstractFileByPath(folderPath + '/' + text + this.plugin.settings.folderNoteType)) { + if ( + this.app.vault.getAbstractFileByPath( + folderPath + '/' + text + this.plugin.settings.folderNoteType, + ) + ) { new Notice('File already exists'); return false; } @@ -221,7 +253,9 @@ export class Commands { this.plugin.app.vault.createFolder(folderPath + '/' + text); createFolderNote(this.plugin, folderPath + '/' + text, false); } - const fileName = this.plugin.settings.folderNoteName.replace('{{folder_name}}', text); + + const { folderNoteName } = this.plugin.settings; + const fileName = folderNoteName.replace('{{folder_name}}', text); if (fileName !== text) { editor.replaceSelection(`[[${fileName}]]`); } else { @@ -234,213 +268,243 @@ export class Commands { }); } - fileCommands() { - this.plugin.registerEvent(this.app.workspace.on('file-menu', (menu: Menu, file: TAbstractFile) => { - let folder: TAbstractFile | TFolder | null = file.parent; - if (file instanceof TFile) { - if (this.plugin.settings.storageLocation === 'insideFolder') { - folder = file.parent; - } else { - const fileName = extractFolderName(this.plugin.settings.folderNoteName, file.basename); - if (fileName) { - if (file.parent?.path === '' || file.parent?.path === '/') { - folder = this.plugin.app.vault.getAbstractFileByPath(fileName); - } else { - folder = this.plugin.app.vault.getAbstractFileByPath(file.parent?.path + '/' + fileName); + fileCommands(): void { + this.plugin.registerEvent( + this.app.workspace.on('file-menu', (menu: Menu, file: TAbstractFile) => { + let folder: TAbstractFile | TFolder | null = file.parent; + if (file instanceof TFile) { + if (this.plugin.settings.storageLocation === 'insideFolder') { + folder = file.parent; + } else { + const { folderNoteName } = this.plugin.settings; + const fileName = extractFolderName(folderNoteName, file.basename); + if (fileName) { + if (file.parent?.path === '' || file.parent?.path === '/') { + folder = this.plugin.app.vault.getAbstractFileByPath(fileName); + } else { + folder = this.plugin.app.vault.getAbstractFileByPath( + file.parent?.path + '/' + fileName, + ); + } } } - } - if (folder instanceof TFolder) { - const folderNote = getFolderNote(this.plugin, folder.path); - const excludedFolder = getExcludedFolder(this.plugin, folder.path, true); - if (folderNote?.path === file.path && !excludedFolder?.detached) { return; } - } else if (file.parent instanceof TFolder) { - folder = file.parent; + if (folder instanceof TFolder) { + const folderNote = getFolderNote(this.plugin, folder.path); + const excludedFolder = getExcludedFolder(this.plugin, folder.path, true); + if (folderNote?.path === file.path && !excludedFolder?.detached) { return; } + } else if (file.parent instanceof TFolder) { + folder = file.parent; + } } - } - menu.addItem(async (item) => { - if (Platform.isDesktop && !Platform.isTablet && this.plugin.settings.useSubmenus) { - item - .setTitle('Folder Note Commands') - .setIcon('folder-edit'); - } - let subMenu: Menu; - if (!Platform.isDesktopApp || !Platform.isDesktop || Platform.isTablet || !this.plugin.settings.useSubmenus) { - subMenu = menu; - item.setDisabled(true); - } else { - // @ts-ignore - subMenu = item.setSubmenu() as Menu; - } - if (file instanceof TFile) { - // @ts-ignore - subMenu.addItem((item) => { - item.setTitle('Create folder note') - .setIcon('edit') - .onClick(async () => { - if (!folder) return; - let newPath = folder.path + '/' + file.basename; - if (folder.path === '' || folder.path === '/') { - newPath = file.basename; - } - if (this.plugin.app.vault.getAbstractFileByPath(newPath)) { - return new Notice('Folder already exists'); - } - const automaticallyCreateFolderNote = this.plugin.settings.autoCreate; - this.plugin.settings.autoCreate = false; - this.plugin.saveSettings(); - await this.plugin.app.vault.createFolder(newPath); - const newFolder = this.plugin.app.vault.getAbstractFileByPath(newPath); - if (!(newFolder instanceof TFolder)) return; - await createFolderNote(this.plugin, newFolder.path, true, '.' + file.extension, false, file); - this.plugin.settings.autoCreate = automaticallyCreateFolderNote; - this.plugin.saveSettings(); - }); - }); - if (getFolderPathFromString(file.path) === '') return; - if (!(folder instanceof TFolder)) return; - if (folder.path === '' || folder.path === '/') return; - subMenu.addItem((item) => { - item.setTitle(`Turn into folder note for ${folder?.name}`) - .setIcon('edit') - .onClick(() => { - if (!folder || !(folder instanceof TFolder)) return; - const folderNote = getFolderNote(this.plugin, folder.path); - turnIntoFolderNote(this.plugin, file, folder, folderNote); - }); - }); - } - if (!(file instanceof TFolder)) return; - const excludedFolder = getExcludedFolder(this.plugin, file.path, false); - const detachedExcludedFolder = getDetachedFolder(this.plugin, file.path); - if (excludedFolder && !excludedFolder.hideInSettings) { - // I'm not sure if I'm ever going to add this because of the possibility that a folder got more than one excluded - // subMenu.addItem((item) => { - // item.setTitle('Manage excluded folder') - // .setIcon('settings-2') - // .onClick(() => { - // if (excludedFolder instanceof ExcludedFolder) { - // new ExcludedFolderSettings(this.plugin.app, this.plugin, excludedFolder).open(); - // } else if (excludedFolder instanceof ExcludePattern) { - // new PatternSettings(this.plugin.app, this.plugin, excludedFolder).open(); - // } - // }) - // }) + // eslint-disable-next-line complexity + menu.addItem(async (menuItem) => { + if ( + Platform.isDesktop && + !Platform.isTablet && + this.plugin.settings.useSubmenus + ) { + menuItem + .setTitle('Folder Note Commands') + .setIcon('folder-edit'); + } + let subMenu: Menu; + if ( + !Platform.isDesktopApp || + !Platform.isDesktop || + Platform.isTablet || + !this.plugin.settings.useSubmenus + ) { + subMenu = menu; + menuItem.setDisabled(true); + } else { + subMenu = menuItem.setSubmenu() as Menu; + } + if (file instanceof TFile) { + subMenu.addItem((subItem) => { + subItem.setTitle('Create folder note') + .setIcon('edit') + .onClick(async () => { + if (!folder) return; + let newPath = folder.path + '/' + file.basename; + if (folder.path === '' || folder.path === '/') { + newPath = file.basename; + } + if (this.plugin.app.vault.getAbstractFileByPath(newPath)) { + return new Notice('Folder already exists'); + } + const automaticallyCreateFolderNote = + this.plugin.settings.autoCreate; + this.plugin.settings.autoCreate = false; + this.plugin.saveSettings(); + await this.plugin.app.vault.createFolder(newPath); + const newFolder = this.plugin.app.vault + .getAbstractFileByPath(newPath); + if (!(newFolder instanceof TFolder)) return; + await createFolderNote( + this.plugin, + newFolder.path, + true, + '.' + file.extension, + false, + file, + ); + this.plugin.settings.autoCreate = automaticallyCreateFolderNote; + this.plugin.saveSettings(); + }); + }); + if (getFolderPathFromString(file.path) === '') return; + if (!(folder instanceof TFolder)) return; + if (folder.path === '' || folder.path === '/') return; + subMenu.addItem((item) => { + item.setTitle(`Turn into folder note for ${folder?.name}`) + .setIcon('edit') + .onClick(() => { + if (!folder || !(folder instanceof TFolder)) return; + const folderNote = getFolderNote(this.plugin, folder.path); + turnIntoFolderNote(this.plugin, file, folder, folderNote); + }); + }); + } + if (!(file instanceof TFolder)) return; + const excludedFolder = getExcludedFolder(this.plugin, file.path, false); + const detachedExcludedFolder = getDetachedFolder(this.plugin, file.path); + if (excludedFolder && !excludedFolder.hideInSettings) { + // I'm not sure if I'm ever going to add this because of the possibility that a folder got more than one excluded + // subMenu.addItem((item) => { + // item.setTitle('Manage excluded folder') + // .setIcon('settings-2') + // .onClick(() => { + // if (excludedFolder instanceof ExcludedFolder) { + // new ExcludedFolderSettings(this.plugin.app, this.plugin, excludedFolder).open(); + // } else if (excludedFolder instanceof ExcludePattern) { + // new PatternSettings(this.plugin.app, this.plugin, excludedFolder).open(); + // } + // }) + // }) + subMenu.addItem((item) => { + item.setTitle('Remove folder from excluded folders') + .setIcon('trash') + .onClick(() => { + this.plugin.settings.excludeFolders = + this.plugin.settings.excludeFolders.filter( + (excluded) => + (excluded.path !== file.path) || excluded.detached, + ); + this.plugin.saveSettings(true); + new Notice('Successfully removed folder from excluded folders'); + }); + }); + return; + } + if (detachedExcludedFolder) { + subMenu.addItem((item) => { + item.setTitle('Remove folder from detached folders') + .setIcon('trash') + .onClick(() => { + deleteExcludedFolder(this.plugin, detachedExcludedFolder); + }); + }); + } + if (detachedExcludedFolder) { return; } subMenu.addItem((item) => { - item.setTitle('Remove folder from excluded folders') - .setIcon('trash') + item.setTitle('Exclude folder from folder notes') + .setIcon('x-circle') .onClick(() => { - this.plugin.settings.excludeFolders = this.plugin.settings.excludeFolders.filter( - (folder) => (folder.path !== file.path) || folder.detached); + const newExcludedFolder = new ExcludedFolder( + file.path, + this.plugin.settings.excludeFolders.length, + undefined, + this.plugin, + ); + this.plugin.settings.excludeFolders.push(newExcludedFolder); this.plugin.saveSettings(true); - new Notice('Successfully removed folder from excluded folders'); + new Notice('Successfully excluded folder from folder notes'); }); }); - return; - } - if (detachedExcludedFolder) { - subMenu.addItem((item) => { - item.setTitle('Remove folder from detached folders') - .setIcon('trash') - .onClick(() => { - deleteExcludedFolder(this.plugin, detachedExcludedFolder); - }); - }); - } - if (detachedExcludedFolder) { return; } - subMenu.addItem((item) => { - item.setTitle('Exclude folder from folder notes') - .setIcon('x-circle') - .onClick(() => { - const excludedFolder = new ExcludedFolder(file.path, this.plugin.settings.excludeFolders.length, undefined, this.plugin); - this.plugin.settings.excludeFolders.push(excludedFolder); - this.plugin.saveSettings(true); - new Notice('Successfully excluded folder from folder notes'); + if (!(file instanceof TFolder)) return; + const folderNote = getFolderNote(this.plugin, file.path); + if (folderNote instanceof TFile && !detachedExcludedFolder) { + subMenu.addItem((item) => { + item.setTitle('Delete folder note') + .setIcon('trash') + .onClick(() => { + deleteFolderNote(this.plugin, folderNote, true); + }); }); - }); - if (!(file instanceof TFolder)) return; - const folderNote = getFolderNote(this.plugin, file.path); - if (folderNote instanceof TFile && !detachedExcludedFolder) { - subMenu.addItem((item) => { - item.setTitle('Delete folder note') - .setIcon('trash') - .onClick(() => { - deleteFolderNote(this.plugin, folderNote, true); - }); - }); - subMenu.addItem((item) => { - item.setTitle('Open folder note') - .setIcon('chevron-right-square') - .onClick(() => { - openFolderNote(this.plugin, folderNote); - }); - }); + subMenu.addItem((item) => { + item.setTitle('Open folder note') + .setIcon('chevron-right-square') + .onClick(() => { + openFolderNote(this.plugin, folderNote); + }); + }); - subMenu.addItem((item) => { - item.setTitle('Detach folder note') - .setIcon('unlink') - .onClick(() => { - detachFolderNote(this.plugin, folderNote); - }); - }); + subMenu.addItem((item) => { + item.setTitle('Detach folder note') + .setIcon('unlink') + .onClick(() => { + detachFolderNote(this.plugin, folderNote); + }); + }); - subMenu.addItem((item) => { - item.setTitle('Copy Obsidian URL') - .setIcon('link') - .onClick(() => { - // @ts-ignore - this.app.copyObsidianUrl(folderNote); - }); - }); + subMenu.addItem((item) => { + item.setTitle('Copy Obsidian URL') + .setIcon('link') + .onClick(() => { + this.app.copyObsidianUrl(folderNote); + }); + }); - if (this.plugin.settings.hideFolderNote) { - if (excludedFolder?.showFolderNote) { - subMenu.addItem((item) => { - item.setTitle('Hide folder note in explorer') - .setIcon('eye-off') - .onClick(() => { - hideFolderNoteInFileExplorer(file.path, this.plugin); - }); - }); - } else { - subMenu.addItem((item) => { - item.setTitle('Show folder note in explorer') - .setIcon('eye') - .onClick(() => { - showFolderNoteInFileExplorer(file.path, this.plugin); - }); - }); + if (this.plugin.settings.hideFolderNote) { + if (excludedFolder?.showFolderNote) { + subMenu.addItem((item) => { + item.setTitle('Hide folder note in explorer') + .setIcon('eye-off') + .onClick(() => { + hideFolderNoteInFileExplorer(file.path, this.plugin); + }); + }); + } else { + subMenu.addItem((item) => { + item.setTitle('Show folder note in explorer') + .setIcon('eye') + .onClick(() => { + showFolderNoteInFileExplorer(file.path, this.plugin); + }); + }); + } } - } - - } else { - subMenu.addItem((item) => { - item.setTitle('Create markdown folder note') - .setIcon('edit') - .onClick(() => { - createFolderNote(this.plugin, file.path, true, '.md'); - }); - }); - this.plugin.settings.supportedFileTypes.forEach((fileType) => { - if (fileType === 'md') return; + } else { subMenu.addItem((item) => { - item.setTitle(`Create ${fileType} folder note`) + item.setTitle('Create markdown folder note') .setIcon('edit') .onClick(() => { - createFolderNote(this.plugin, file.path, true, '.' + fileType); + createFolderNote(this.plugin, file.path, true, '.md'); }); }); - }); - } - }); - })); + + this.plugin.settings.supportedFileTypes.forEach((fileType) => { + if (fileType === 'md') return; + subMenu.addItem((item) => { + item.setTitle(`Create ${fileType} folder note`) + .setIcon('edit') + .onClick(() => { + // eslint-disable-next-line max-len + createFolderNote(this.plugin, file.path, true, '.' + fileType); + }); + }); + }); + } + }); + })); } - editorCommands() { + editorCommands(): void { + // eslint-disable-next-line max-len this.plugin.registerEvent(this.plugin.app.workspace.on('editor-menu', (menu: Menu, editor: Editor, view: MarkdownView) => { const text = editor.getSelection().trim(); if (!text || text.trim() === '') return; @@ -453,6 +517,7 @@ export class Commands { const blacklist = ['*', '\\', '"', '/', '<', '>', '?', '|', ':']; for (const char of blacklist) { if (text.includes(char)) { + // eslint-disable-next-line max-len new Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?'); return; } @@ -461,9 +526,11 @@ export class Commands { new Notice('File name cannot end with a dot'); return; } + let folder: TAbstractFile | null; const folderPath = getFolderPathFromString(file.path); - const fileName = this.plugin.settings.folderNoteName.replace('{{folder_name}}', text); + const { folderNoteName } = this.plugin.settings; + const fileName = folderNoteName.replace('{{folder_name}}', text); if (folderPath === '') { folder = this.plugin.app.vault.getAbstractFileByPath(text); if (folder instanceof TFolder) { @@ -473,12 +540,21 @@ export class Commands { createFolderNote(this.plugin, text, false); } else { - folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + '/' + text); + folder = this.plugin.app.vault.getAbstractFileByPath( + folderPath + '/' + text, + ); if (folder instanceof TFolder) { return new Notice('Folder note already exists'); } if (this.plugin.settings.storageLocation === 'parentFolder') { - if (this.app.vault.getAbstractFileByPath(folderPath + '/' + fileName + this.plugin.settings.folderNoteType)) { + if ( + this.app.vault.getAbstractFileByPath( + folderPath + + '/' + + fileName + + this.plugin.settings.folderNoteType, + ) + ) { return new Notice('File already exists'); } } diff --git a/src/functions/ListComponent.ts b/src/functions/ListComponent.ts index 0c8e21e..f6486a8 100644 --- a/src/functions/ListComponent.ts +++ b/src/functions/ListComponent.ts @@ -18,19 +18,19 @@ export class ListComponent { this.defaultValues = defaultValues; } - on(event: string, listener: (data?: any) => void) { + on(event: string, listener: (data?: unknown) => void): void { this.emitter.on(event, listener); } - off(event: string, listener: (data?: any) => void) { + off(event: string, listener: (data?: unknown) => void): void { this.emitter.off(event, listener); } - private emit(event: string, data?: any) { + private emit(event: string, data?: unknown): void { this.emitter.emit(event, data); } - setValues(values: string[]) { + setValues(values: string[]): void { this.removeElements(); this.values = values; if (values.length !== 0) { @@ -41,11 +41,11 @@ export class ListComponent { this.emit('update', this.values); } - removeElements() { + removeElements(): void { this.listEl.empty(); } - addElement(value: string) { + addElement(value: string): void { this.listEl.createSpan('setting-hotkey', (span) => { if (value.toLocaleLowerCase() === 'md') { span.innerText = 'markdown'; @@ -53,35 +53,39 @@ export class ListComponent { span.innerText = value; } span.setAttribute('extension', value); + // eslint-disable-next-line max-len const removeSpan = span.createEl('span', { cls: 'ofn-list-item-remove setting-hotkey-icon' }); + // eslint-disable-next-line max-len const svg = ''; const svgElement = removeSpan.createEl('span', { cls: 'ofn-list-item-remove-icon' }); svgElement.innerHTML = svg; - removeSpan.onClickEvent((e) => { + removeSpan.onClickEvent(() => { this.removeValue(value); span.remove(); }); }); } - async addValue(value: string) { + async addValue(value: string): Promise { this.values.push(value); this.addElement(value); this.emit('add', value); this.emit('update', this.values); } - addResetButton() { + addResetButton(): this { + // eslint-disable-next-line max-len const resetButton = this.controlEl.createEl('span', { cls: 'clickable-icon setting-restore-hotkey-button' }); + // eslint-disable-next-line max-len const svg = ''; resetButton.innerHTML = svg; - resetButton.onClickEvent((e) => { + resetButton.onClickEvent(() => { this.setValues(this.defaultValues); }); return this; } - removeValue(value: string) { + removeValue(value: string): void { this.values = this.values.filter((v) => v !== value); this.listEl.find(`[extension='${value}']`).remove(); this.emit('remove', value); diff --git a/src/functions/excalidraw.ts b/src/functions/excalidraw.ts index 81eb8c8..8b0286e 100644 --- a/src/functions/excalidraw.ts +++ b/src/functions/excalidraw.ts @@ -1,19 +1,36 @@ import type { WorkspaceLeaf, App } from 'obsidian'; -export async function openExcalidrawView(leaf: WorkspaceLeaf) { - const { excalidraw, excalidrawEnabled } = await getExcalidrawPlugin(this.app); - if (excalidrawEnabled) { +interface ExcalidrawPlugin { + setExcalidrawView(leaf: WorkspaceLeaf): void; +} + +export async function openExcalidrawView( + app: App, + leaf: WorkspaceLeaf, +): Promise { + const { excalidraw, excalidrawEnabled } = await getExcalidrawPlugin(app); + if (excalidrawEnabled && excalidraw) { excalidraw.setExcalidrawView(leaf); } } -export async function getExcalidrawPlugin(app: App) { - const excalidraw = (app as any).plugins.plugins['obsidian-excalidraw-plugin']; - const excalidrawEnabled = (app as any).plugins.enabledPlugins.has( - 'obsidian-excalidraw-plugin', +export async function getExcalidrawPlugin( + app: App, +): Promise<{ excalidraw: ExcalidrawPlugin | null; excalidrawEnabled: boolean }> { + const { plugins: pluginManager } = app as App & { + plugins: { + plugins: Record; + enabledPlugins: Set; + }; + }; + const excalidraw = ( + pluginManager.plugins[ + 'obsidian-excalidraw-plugin' + ] as unknown as ExcalidrawPlugin | undefined ); + const excalidrawEnabled = pluginManager.enabledPlugins.has('obsidian-excalidraw-plugin'); return { - excalidraw, + excalidraw: excalidraw ?? null, excalidrawEnabled, }; } diff --git a/src/functions/folderNoteFunctions.ts b/src/functions/folderNoteFunctions.ts index 17f6944..69e1830 100644 --- a/src/functions/folderNoteFunctions.ts +++ b/src/functions/folderNoteFunctions.ts @@ -1,15 +1,39 @@ +/* eslint-disable complexity */ +/* eslint-disable max-len */ import type FolderNotesPlugin from '../main'; import ExistingFolderNoteModal from '../modals/ExistingNote'; import { applyTemplate } from '../template'; -import type { TAbstractFile } from 'obsidian'; -import { TFolder, TFile, Keymap } from 'obsidian'; +import { + TFolder, + TFile, + Keymap, + type TAbstractFile, + type MarkdownView, + type WorkspaceLeaf, +} from 'obsidian'; import DeleteConfirmationModal from '../modals/DeleteConfirmation'; -import { addExcludedFolder, deleteExcludedFolder, getDetachedFolder, getExcludedFolder, updateExcludedFolder } from '../ExcludeFolders/functions/folderFunctions'; +import { + addExcludedFolder, + deleteExcludedFolder, + getDetachedFolder, + getExcludedFolder, + updateExcludedFolder, +} from '../ExcludeFolders/functions/folderFunctions'; import { ExcludedFolder } from '../ExcludeFolders/ExcludeFolder'; import { openExcalidrawView } from './excalidraw'; import { AskForExtensionModal } from 'src/modals/AskForExtension'; -import { addCSSClassToFileExplorerEl, removeCSSClassFromFileExplorerEL, removeActiveFolder, setActiveFolder } from 'src/functions/styleFunctions'; -import { getFolderNameFromPathString, getFolderPathFromString, removeExtension } from 'src/functions/utils'; +import { + addCSSClassToFileExplorerEl, + removeCSSClassFromFileExplorerEL, + removeActiveFolder, + setActiveFolder, +} from 'src/functions/styleFunctions'; +import { + getFolderNameFromPathString, + getFolderPathFromString, + removeExtension, +} from 'src/functions/utils'; + const defaultExcalidrawTemplate = `--- @@ -27,24 +51,36 @@ tags: [excalidraw] \`\`\` %%`; -export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: string, openFile: boolean, extension?: string, displayModal?: boolean, preexistingNote?: TFile) { - const leaf = plugin.app.workspace.getLeaf(false); - const folderName = getFolderNameFromPathString(folderPath); - const fileName = plugin.settings.folderNoteName.replace('{{folder_name}}', folderName); - let folderNote = getFolderNote(plugin, folderPath); - if (preexistingNote) { - folderNote = preexistingNote; - } - let folderNoteType = extension ?? plugin.settings.folderNoteType; - const detachedFolder = getDetachedFolder(plugin, folderPath); - let path = ''; +export async function createFolderNote( + plugin: FolderNotesPlugin, + folderPath: string, + openFile: boolean, + extension?: string, + displayModal?: boolean, + preexistingNote?: TFile, +): Promise { + let { + leaf, + fileName, + folderNote, + folderNoteType, + detachedFolder, + path, + } = getArgs(plugin, folderPath, extension, preexistingNote); if (folderNoteType === '.excalidraw') { folderNoteType = '.md'; extension = '.excalidraw'; } else if (folderNoteType === '.ask') { if (plugin.askModalCurrentlyOpen) return; - return new AskForExtensionModal(plugin, folderPath, openFile, folderNoteType, displayModal, preexistingNote).open(); + return new AskForExtensionModal( + plugin, + folderPath, + openFile, + folderNoteType, + displayModal, + preexistingNote, + ).open(); } if (plugin.settings.storageLocation === 'parentFolder') { @@ -61,27 +97,7 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st } if (detachedFolder && folderNote?.extension !== extension && folderNote) { - deleteExcludedFolder(plugin, detachedFolder); - removeCSSClassFromFileExplorerEL(folderNote?.path, 'is-folder-note', false, plugin); - const folder = plugin.app.vault.getAbstractFileByPath(folderPath) as TFolder; - if (!folderNote || folderNote.basename !== fileName) return; - let count = 1; - let newName = removeExtension(folderNote.path) + ` (${count}).${folderNote.path.split('.').pop()}`; - while (count < 100 && plugin.app.vault.getAbstractFileByPath(newName)) { - count++; - newName = removeExtension(folderNote.path) + ` (${count}).${folderNote.path.split('.').pop()}`; - } - const [excludedFolder, excludedFolderExisted, disabledSync] = await tempDisableSync(plugin, folder); - - await plugin.app.fileManager.renameFile(folderNote, newName).then(() => { - if (!excludedFolder) return; - if (!excludedFolderExisted) { - deleteExcludedFolder(plugin, excludedFolder); - } else if (!disabledSync) { - excludedFolder.disableSync = false; - updateExcludedFolder(plugin, excludedFolder, excludedFolder); - } - }); + await handleTurnNoteIntoFolderNote(plugin, folderNote, detachedFolder, folderPath, fileName); } if (!extension) { @@ -89,33 +105,7 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st } if (!folderNote) { - let content = ''; - if (extension !== '.md' && extension) { - if (plugin.settings.templatePath && folderNoteType.split('.').pop() === plugin.settings.templatePath.split('.').pop()) { - const templateFile = plugin.app.vault.getAbstractFileByPath(plugin.settings.templatePath); - if (templateFile instanceof TFile) { - if (['md', 'canvas', 'txt'].includes(templateFile.extension)) { - content = await plugin.app.vault.read(templateFile); - if (extension === '.excalidraw' && !content.includes('==âš  Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. âš ==')) { - content = defaultExcalidrawTemplate; - } - } else { - return plugin.app.vault.readBinary(templateFile).then(async (data) => { - folderNote = await plugin.app.vault.createBinary(path, data); - if (openFile) { - await leaf.openFile(folderNote); - } - }); - } - } - } else if (plugin.settings.folderNoteType === '.excalidraw' || extension === '.excalidraw') { - content = defaultExcalidrawTemplate; - } else if (plugin.settings.folderNoteType === '.canvas') { - content = '{}'; - } - } - - folderNote = await plugin.app.vault.create(path, content); + folderNote = await handleCreateFolderNote(plugin, folderNoteType, openFile, leaf, folderNote, path, extension); } else { await plugin.app.fileManager.renameFile(folderNote, path); } @@ -131,11 +121,13 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st } await leaf.openFile(folderNote); if (plugin.settings.folderNoteType === '.excalidraw' || extension === '.excalidraw') { - openExcalidrawView(leaf); + openExcalidrawView(plugin.app, leaf); } } - const matchingExtension = extension?.split('.').pop() === plugin.settings.templatePath.split('.').pop(); + const matchingExtension = + extension?.split('.').pop() === + plugin.settings.templatePath.split('.').pop(); if (folderNote && matchingExtension && plugin.settings.folderNoteType !== '.excalidraw') { applyTemplate(plugin, folderNote, leaf, plugin.settings.templatePath); } @@ -146,19 +138,159 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st addCSSClassToFileExplorerEl(folder.path, 'has-folder-note', false, plugin); } -export async function turnIntoFolderNote(plugin: FolderNotesPlugin, file: TFile, folder: TFolder, folderNote?: TFile | null | TAbstractFile, skipConfirmation?: boolean) { +function getArgs( + plugin: FolderNotesPlugin, + folderPath: string, + extension?: string, + preexistingNote?: TFile, +): { + leaf: WorkspaceLeaf; + fileName: string; + folderNote: TFile | null | undefined; + folderNoteType: string; + detachedFolder: ExcludedFolder | undefined; + path: string | ''; +} { + const leaf = plugin.app.workspace.getLeaf(false); + const folderName = getFolderNameFromPathString(folderPath); + const fileName = plugin.settings.folderNoteName.replace('{{folder_name}}', folderName); + let folderNote = getFolderNote(plugin, folderPath); + if (preexistingNote) { + folderNote = preexistingNote; + } + let folderNoteType = extension ?? plugin.settings.folderNoteType; + const detachedFolder = getDetachedFolder(plugin, folderPath); + let path = ''; + + return { + leaf, + fileName, + folderNote, + folderNoteType, + detachedFolder, + path, + }; +} + +async function handleCreateFolderNote(plugin: FolderNotesPlugin, folderNoteType: string, openFile: boolean, leaf: WorkspaceLeaf, folderNote: TFile | null | undefined, path: string, extension?: string): Promise { + let content = ''; + if (extension !== '.md' && extension) { + if ( + plugin.settings.templatePath && + folderNoteType.split('.').pop() === + plugin.settings.templatePath.split('.').pop() + ) { + const templateFile = plugin.app.vault.getAbstractFileByPath( + plugin.settings.templatePath, + ); + if (templateFile instanceof TFile) { + if (['md', 'canvas', 'txt'].includes(templateFile.extension)) { + content = await plugin.app.vault.read(templateFile); + if ( + extension === '.excalidraw' && + !content.includes( + '==âš  Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. âš ==', + ) + ) { + content = defaultExcalidrawTemplate; + } + } else { + plugin.app.vault.readBinary(templateFile).then(async (data) => { + folderNote = await plugin.app.vault.createBinary(path, data); + if (openFile) { + await leaf.openFile(folderNote); + } + return folderNote; + }); + } + } + } else if ( + plugin.settings.folderNoteType === '.excalidraw' || + extension === '.excalidraw' + ) { + content = defaultExcalidrawTemplate; + } else if (plugin.settings.folderNoteType === '.canvas') { + content = '{}'; + } + } + + folderNote = await plugin.app.vault.create(path, content); + return folderNote; +} + +async function handleTurnNoteIntoFolderNote( + plugin: FolderNotesPlugin, + folderNote: TFile, + detachedFolder: ExcludedFolder, + folderPath: string, + fileName: string, +): Promise { + deleteExcludedFolder(plugin, detachedFolder); + removeCSSClassFromFileExplorerEL(folderNote?.path, 'is-folder-note', false, plugin); + const folder = plugin.app.vault.getAbstractFileByPath(folderPath) as TFolder; + if (!folderNote || folderNote.basename !== fileName) return; + let count = 1; + const baseName = removeExtension(folderNote.path); + const ext = folderNote.path.split('.').pop(); + let newName = `${baseName} (${count}).${ext}`; + const MAX_FOLDER_NOTE_RENAME_ATTEMPTS = 100; + + while ( + count < MAX_FOLDER_NOTE_RENAME_ATTEMPTS && + plugin.app.vault.getAbstractFileByPath(newName) + ) { + count++; + newName = `${baseName} (${count}).${ext}`; + } + const [ + excludedFolder, + excludedFolderExisted, + disabledSync, + ] = await tempDisableSync(plugin, folder); + + await plugin.app.fileManager.renameFile(folderNote, newName).then(() => { + if (!excludedFolder) return; + if (!excludedFolderExisted) { + deleteExcludedFolder(plugin, excludedFolder); + } else if (!disabledSync) { + excludedFolder.disableSync = false; + updateExcludedFolder(plugin, excludedFolder, excludedFolder); + } + }); +} + +export async function turnIntoFolderNote( + plugin: FolderNotesPlugin, + file: TFile, + folder: TFolder, + folderNote?: TFile | null | TAbstractFile, + skipConfirmation?: boolean, +): Promise { const { extension } = file; const detachedExcludedFolder = getDetachedFolder(plugin, folder.path); if (folderNote) { - if (plugin.settings.showRenameConfirmation && !skipConfirmation && !detachedExcludedFolder) { + if ( + plugin.settings.showRenameConfirmation && + !skipConfirmation && + !detachedExcludedFolder + ) { return new ExistingFolderNoteModal(plugin.app, plugin, file, folder, folderNote).open(); } removeCSSClassFromFileExplorerEL(folderNote.path, 'is-folder-note', false, plugin); - const [excludedFolder, excludedFolderExisted, disabledSync] = await tempDisableSync(plugin, folder); + const [ + excludedFolder, + excludedFolderExisted, + disabledSync, + ] = await tempDisableSync(plugin, folder); + + const CTIME_SLICE_START = 10; + const RANDOM_SUFFIX_MAX = 1000; + const randomSuffix = Math.floor(Math.random() * RANDOM_SUFFIX_MAX); + const ctimeSuffix = file.stat.ctime.toString().slice(CTIME_SLICE_START); + const newPath = `${folder.path}/${folder.name} (${ctimeSuffix}${randomSuffix}).${extension}`; - const newPath = `${folder.path}/${folder.name} (${file.stat.ctime.toString().slice(10) + Math.floor(Math.random() * 1000)}).${extension}`; plugin.app.fileManager.renameFile(folderNote, newPath).then(() => { if (!excludedFolder) return; if (!excludedFolderExisted) { @@ -195,14 +327,28 @@ export async function turnIntoFolderNote(plugin: FolderNotesPlugin, file: TFile, setActiveFolder(folder.path, plugin); } -export async function tempDisableSync(plugin: FolderNotesPlugin, folder: TFolder): Promise<[excludedFolder: ExcludedFolder | undefined, excludedFolderExisted: boolean, disabledSync: boolean]> { +export async function tempDisableSync( + plugin: FolderNotesPlugin, + folder: TFolder, +): Promise< + [ + excludedFolder: ExcludedFolder | undefined, + excludedFolderExisted: boolean, + disabledSync: boolean + ] +> { let excludedFolder = getExcludedFolder(plugin, folder.path, false); let excludedFolderExisted = true; let disabledSync = false; if (!excludedFolder) { excludedFolderExisted = false; - excludedFolder = new ExcludedFolder(folder.path, plugin.settings.excludeFolders.length, undefined, plugin); + excludedFolder = new ExcludedFolder( + folder.path, + plugin.settings.excludeFolders.length, + undefined, + plugin, + ); excludedFolder.disableSync = true; addExcludedFolder(plugin, excludedFolder); } else if (!excludedFolder.disableSync) { @@ -214,7 +360,11 @@ export async function tempDisableSync(plugin: FolderNotesPlugin, folder: TFolder return [excludedFolder, excludedFolderExisted, disabledSync]; } -export async function openFolderNote(plugin: FolderNotesPlugin, file: TAbstractFile, evt?: MouseEvent) { +export async function openFolderNote( + plugin: FolderNotesPlugin, + file: TAbstractFile, + evt?: MouseEvent, +): Promise { const { path } = file; const focusExistingTab = plugin.settings.focusExistingTab && plugin.settings.openInNewTab; const activeFilePath = plugin.app.workspace.getActiveFile()?.path; @@ -230,7 +380,7 @@ export async function openFolderNote(plugin: FolderNotesPlugin, file: TAbstractF plugin.app.workspace.iterateAllLeaves((leaf) => { if ( leaf.getViewState().type === 'markdown' && - (leaf.view as import('obsidian').MarkdownView).file?.path === path + (leaf.view as MarkdownView).file?.path === path ) { foundLeaf = leaf; } @@ -240,14 +390,19 @@ export async function openFolderNote(plugin: FolderNotesPlugin, file: TAbstractF if (foundLeaf) { plugin.app.workspace.setActiveLeaf(foundLeaf, { focus: true }); } else { - const leaf = plugin.app.workspace.getLeaf(Keymap.isModEvent(evt) || plugin.settings.openInNewTab); + const shouldOpenInNewTab = Keymap.isModEvent(evt) || plugin.settings.openInNewTab; + const leaf = plugin.app.workspace.getLeaf(shouldOpenInNewTab); if (file instanceof TFile) { await leaf.openFile(file); } } } -export async function deleteFolderNote(plugin: FolderNotesPlugin, file: TFile, displayModal: boolean) { +export async function deleteFolderNote( + plugin: FolderNotesPlugin, + file: TFile, + displayModal: boolean, +): Promise { if (plugin.settings.showDeleteConfirmation && displayModal) { return new DeleteConfirmationModal(plugin.app, plugin, file).open(); } @@ -272,7 +427,7 @@ export async function deleteFolderNote(plugin: FolderNotesPlugin, file: TFile, d } } -export function extractFolderName(template: string, changedFileName: string) { +export function extractFolderName(template: string, changedFileName: string): string | null { const [prefix, suffix] = template.split('{{folder_name}}'); if (prefix.trim() === '' && suffix.trim() === '') { return changedFileName; @@ -288,39 +443,23 @@ export function extractFolderName(template: string, changedFileName: string) { return null; } -export function getFolderNote(plugin: FolderNotesPlugin, folderPath: string, storageLocation?: string, file?: TFile, oldFolderNoteName?: string) { - if (!folderPath) return null; - const folder = { - path: folderPath, - name: getFolderNameFromPathString(folderPath), - }; - const folderNoteName = oldFolderNoteName ?? plugin.settings.folderNoteName; - - let fileName = folderNoteName.replace('{{folder_name}}', folder.name); - if (file) { - fileName = folderNoteName.replace('{{folder_name}}', file.basename); - } - if (!fileName) return null; - - if ((plugin.settings.storageLocation === 'parentFolder' || storageLocation === 'parentFolder') && storageLocation !== 'insideFolder') { - folder.path = getFolderPathFromString(folderPath); +function findFolderNoteFile( + plugin: FolderNotesPlugin, + path: string, + primaryType: string, +): TFile | null { + let folderNote = plugin.app.vault.getAbstractFileByPath(path + primaryType); + if ( + folderNote instanceof TFile && + plugin.settings.supportedFileTypes.includes(primaryType.replace('.', '')) + ) { + return folderNote; } + const supportedFileTypes = plugin.settings.supportedFileTypes.filter( + (type) => type !== primaryType.replace('.', ''), + ); - let path = `${folder.path}/${fileName}`; - folder.path === '/' ? path = fileName : path = `${folder.path}/${fileName}`; - - - let { folderNoteType } = plugin.settings; - if (folderNoteType === '.excalidraw') { - folderNoteType = '.md'; - } - - let folderNote = plugin.app.vault.getAbstractFileByPath(path + folderNoteType); - if (folderNote instanceof TFile && plugin.settings.supportedFileTypes.includes(plugin.settings.folderNoteType.replace('.', ''))) { - return folderNote; - } - const supportedFileTypes = plugin.settings.supportedFileTypes.filter((type) => type !== plugin.settings.folderNoteType.replace('.', '')); for (let type of supportedFileTypes) { if (type === 'excalidraw' || type === '.excalidraw') { type = '.md'; @@ -333,13 +472,40 @@ export function getFolderNote(plugin: FolderNotesPlugin, folderPath: string, sto return folderNote; } } + return null; +} + +export function getFolderNote( + plugin: FolderNotesPlugin, + folderPath: string, + storageLocation?: string, + file?: TFile, + oldFolderNoteName?: string, +): TFile | null | undefined { + const folder = getFolderInfo(folderPath); + if (!folder) return null; + + let fileName = resolveFileName(plugin, folder, file, oldFolderNoteName); + if (!fileName) return null; + adjustFolderPathForStorage(folder, folderPath, plugin, storageLocation); + + const path = buildFullPath(folder, fileName); + const primaryType = normalizeFolderNoteType(plugin.settings.folderNoteType); + + return findFolderNoteFile(plugin, path, primaryType); } -export function detachFolderNote(plugin: FolderNotesPlugin, file: TFile) { + +export function detachFolderNote(plugin: FolderNotesPlugin, file: TFile): void { const folder = getFolder(plugin, file); if (!folder) return; - const excludedFolder = new ExcludedFolder(folder.path, plugin.settings.excludeFolders.length, undefined, plugin); + const excludedFolder = new ExcludedFolder( + folder.path, + plugin.settings.excludeFolders.length, + undefined, + plugin, + ); excludedFolder.hideInSettings = true; excludedFolder.disableFolderNote = true; excludedFolder.disableSync = true; @@ -351,16 +517,28 @@ export function detachFolderNote(plugin: FolderNotesPlugin, file: TFile) { } -export function getFolder(plugin: FolderNotesPlugin, file: TFile, storageLocation?: string) { +export function getFolder( + plugin: FolderNotesPlugin, + file: TFile, + storageLocation?: string, +): TFolder | TAbstractFile | null { if (!file) return null; let folderName = extractFolderName(plugin.settings.folderNoteName, file.basename); - if (plugin.settings.folderNoteName === file.basename && plugin.settings.storageLocation === 'insideFolder') { + if ( + plugin.settings.folderNoteName === file.basename && + plugin.settings.storageLocation === 'insideFolder' + ) { folderName = file.parent?.name ?? ''; } if (!folderName) return null; let folderPath = getFolderPathFromString(file.path); let folder: TFolder | TAbstractFile | null = null; - if ((plugin.settings.storageLocation === 'parentFolder' || storageLocation === 'parentFolder') && storageLocation !== 'insideFolder') { + + if ( + (plugin.settings.storageLocation === 'parentFolder' || + storageLocation === 'parentFolder') && + storageLocation !== 'insideFolder' + ) { if (folderPath.trim() === '' || folderPath === '/') { folderPath = folderName; } else { @@ -370,11 +548,16 @@ export function getFolder(plugin: FolderNotesPlugin, file: TFile, storageLocatio } else { folder = plugin.app.vault.getAbstractFileByPath(folderPath); } + if (!folder) { return null; } return folder; } -export function getFolderNoteFolder(plugin: FolderNotesPlugin, folderNote: TFile | string, fileName: string) { +export function getFolderNoteFolder( + plugin: FolderNotesPlugin, + folderNote: TFile | string, + fileName: string, +): TFolder | TAbstractFile | null { if (!folderNote) return null; let filePath = ''; if (typeof folderNote === 'string') { @@ -399,3 +582,46 @@ export function getFolderNoteFolder(plugin: FolderNotesPlugin, folderNote: TFile if (!folder) { return null; } return folder; } + +function getFolderInfo(folderPath: string): { path: string; name: string } | null { + if (!folderPath) return null; + return { + path: folderPath, + name: getFolderNameFromPathString(folderPath), + }; +} + +function resolveFileName( + plugin: FolderNotesPlugin, + folder: { path: string; name: string }, + file?: TFile, + oldFolderNoteName?: string, +): string | null { + const templateName = oldFolderNoteName ?? plugin.settings.folderNoteName; + if (!templateName) return null; + const nameSource = file ? file.basename : folder.name; + return templateName.replace('{{folder_name}}', nameSource); +} + +function adjustFolderPathForStorage( + folder: { path: string; name: string }, + folderPath: string, + plugin: FolderNotesPlugin, + storageLocation?: string, +): void { + if ( + (plugin.settings.storageLocation === 'parentFolder' || + storageLocation === 'parentFolder') && + storageLocation !== 'insideFolder' + ) { + folder.path = getFolderPathFromString(folderPath); + } +} + +function buildFullPath(folder: { path: string }, fileName: string): string { + return folder.path === '/' ? fileName : `${folder.path}/${fileName}`; +} + +function normalizeFolderNoteType(type: string): string { + return type === '.excalidraw' ? '.md' : type; +} diff --git a/src/functions/styleFunctions.ts b/src/functions/styleFunctions.ts index d65d886..a99c6b8 100644 --- a/src/functions/styleFunctions.ts +++ b/src/functions/styleFunctions.ts @@ -1,6 +1,10 @@ import { TFile, TFolder } from 'obsidian'; import type FolderNotesPlugin from '../main'; -import { getDetachedFolder, getExcludedFolder, addExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; +import { + getDetachedFolder, + getExcludedFolder, + addExcludedFolder, +} from 'src/ExcludeFolders/functions/folderFunctions'; import { getFolder, getFolderNote } from 'src/functions/folderNoteFunctions'; import { getFileExplorer } from './utils'; import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; @@ -9,7 +13,7 @@ import type FolderOverviewPlugin from 'src/obsidian-folder-overview/src/main'; /** * @description Refreshes the CSS classes for all folder notes in the file explorer. */ -export function refreshAllFolderStyles(forceReload = false, plugin: FolderNotesPlugin) { +export function refreshAllFolderStyles(forceReload = false, plugin: FolderNotesPlugin): void { if (plugin.activeFileExplorer === getFileExplorer(plugin) && !forceReload) { return; } plugin.activeFileExplorer = getFileExplorer(plugin); plugin.app.vault.getAllLoadedFiles().forEach(async (file) => { @@ -22,7 +26,10 @@ export function refreshAllFolderStyles(forceReload = false, plugin: FolderNotesP /** * @description Updates the CSS classes for a specific folder in the file explorer. */ -export async function updateCSSClassesForFolder(folderPath: string, plugin: FolderNotesPlugin) { +export async function updateCSSClassesForFolder( + folderPath: string, + plugin: FolderNotesPlugin, +): Promise { const folder = plugin.app.vault.getAbstractFileByPath(folderPath); if (!folder || !(folder instanceof TFolder)) { return; } @@ -64,7 +71,10 @@ export async function updateCSSClassesForFolder(folderPath: string, plugin: Fold /** * @description Updates the CSS classes for a folder note file in the file explorer and then also updates the folder it belongs to. */ -export async function updateCSSClassesForFolderNote(filePath: string, plugin: FolderNotesPlugin) { +export async function updateCSSClassesForFolderNote( + filePath: string, + plugin: FolderNotesPlugin, +): Promise { const file = plugin.app.vault.getAbstractFileByPath(filePath); if (!file || !(file instanceof TFile)) { return; } @@ -74,17 +84,25 @@ export async function updateCSSClassesForFolderNote(filePath: string, plugin: Fo updateCSSClassesForFolder(folder.path, plugin); } -export function markFolderAndNoteWithClasses(file: TFile, folder: TFolder, plugin: FolderNotesPlugin) { +export function markFolderAndNoteWithClasses( + file: TFile, + folder: TFolder, + plugin: FolderNotesPlugin, +): void { markFileAsFolderNote(file, plugin); markFolderWithFolderNoteClasses(folder, plugin); } -export function clearFolderAndNoteClasses(folder: TFolder, file: TFile, plugin: FolderNotesPlugin) { +export function clearFolderAndNoteClasses( + folder: TFolder, + file: TFile, + plugin: FolderNotesPlugin, +): void { unmarkFileAsFolderNote(file, plugin); clearFolderNoteClassesFromFolder(folder, plugin); } -export function markFolderWithFolderNoteClasses(folder: TFolder, plugin: FolderNotesPlugin) { +export function markFolderWithFolderNoteClasses(folder: TFolder, plugin: FolderNotesPlugin): void { addCSSClassToFileExplorerEl(folder.path, 'has-folder-note', false, plugin); if (plugin.isEmptyFolderNoteFolder(folder) && getFolderNote(plugin, folder.path)) { addCSSClassToFileExplorerEl(folder.path, 'only-has-folder-note', true, plugin); @@ -93,20 +111,20 @@ export function markFolderWithFolderNoteClasses(folder: TFolder, plugin: FolderN } } -export function markFileAsFolderNote(file: TFile, plugin: FolderNotesPlugin) { +export function markFileAsFolderNote(file: TFile, plugin: FolderNotesPlugin): void { addCSSClassToFileExplorerEl(file.path, 'is-folder-note', false, plugin); } -export function unmarkFileAsFolderNote(file: TFile, plugin: FolderNotesPlugin) { +export function unmarkFileAsFolderNote(file: TFile, plugin: FolderNotesPlugin): void { removeCSSClassFromFileExplorerEL(file.path, 'is-folder-note', false, plugin); } -export function unmarkFolderAsFolderNote(folder: TFolder, plugin: FolderNotesPlugin) { +export function unmarkFolderAsFolderNote(folder: TFolder, plugin: FolderNotesPlugin): void { removeCSSClassFromFileExplorerEL(folder.path, 'has-folder-note', false, plugin); removeCSSClassFromFileExplorerEL(folder.path, 'only-has-folder-note', true, plugin); } -export function clearFolderNoteClassesFromFolder(folder: TFolder, plugin: FolderNotesPlugin) { +export function clearFolderNoteClassesFromFolder(folder: TFolder, plugin: FolderNotesPlugin): void { removeCSSClassFromFileExplorerEL(folder.path, 'has-folder-note', false, plugin); removeCSSClassFromFileExplorerEL(folder.path, 'only-has-folder-note', true, plugin); } @@ -115,11 +133,21 @@ export function clearFolderNoteClassesFromFolder(folder: TFolder, plugin: Folder * @param path Can be a folder or file path * @returns nothing */ -export async function addCSSClassToFileExplorerEl(path: string, cssClass: string, parent = false, plugin: FolderNotesPlugin, waitForCreate = false, count = 0) { +export async function addCSSClassToFileExplorerEl( + path: string, + cssClass: string, + parent = false, + plugin: FolderNotesPlugin, + waitForCreate = false, + count = 0, +): Promise { const fileExplorerItem = getFileExplorerElement(path, plugin); + const MAX_RETRIES = 5; + const RETRY_DELAY = 500; + if (!fileExplorerItem) { - if (waitForCreate && count < 5) { - await new Promise((r) => setTimeout(r, 500)); + if (waitForCreate && count < MAX_RETRIES) { + await new Promise((r) => setTimeout(r, RETRY_DELAY)); addCSSClassToFileExplorerEl(path, cssClass, parent, plugin, waitForCreate, count + 1); return; } @@ -143,7 +171,12 @@ export async function addCSSClassToFileExplorerEl(path: string, cssClass: string * @param cssClass The CSS class to remove from the file explorer element * @returns nothing */ -export function removeCSSClassFromFileExplorerEL(path: string | undefined, cssClass: string, parent: boolean, plugin: FolderNotesPlugin) { +export function removeCSSClassFromFileExplorerEL( + path: string | undefined, + cssClass: string, + parent: boolean, + plugin: FolderNotesPlugin, +): void { if (!path) return; const fileExplorerItem = getFileExplorerElement(path, plugin); document.querySelectorAll(`[data-path='${CSS.escape(path)}']`).forEach((item) => { @@ -161,15 +194,23 @@ export function removeCSSClassFromFileExplorerEL(path: string | undefined, cssCl } -export function getFileExplorerElement(path: string, plugin: FolderNotesPlugin | FolderOverviewPlugin): HTMLElement | null { +export function getFileExplorerElement( + path: string, + plugin: FolderNotesPlugin | FolderOverviewPlugin, +): HTMLElement | null { const fileExplorer = getFileExplorer(plugin); if (!fileExplorer?.view?.fileItems) { return null; } const fileExplorerItem = fileExplorer.view.fileItems?.[path]; return fileExplorerItem?.selfEl ?? fileExplorerItem?.titleEl ?? null; } -export function showFolderNoteInFileExplorer(path: string, plugin: FolderNotesPlugin) { - const excludedFolder = new ExcludedFolder(path, plugin.settings.excludeFolders.length, undefined, plugin); +export function showFolderNoteInFileExplorer(path: string, plugin: FolderNotesPlugin): void { + const excludedFolder = new ExcludedFolder( + path, + plugin.settings.excludeFolders.length, + undefined, + plugin, + ); excludedFolder.subFolders = false; excludedFolder.disableSync = false; excludedFolder.disableAutoCreate = false; @@ -183,7 +224,7 @@ export function showFolderNoteInFileExplorer(path: string, plugin: FolderNotesPl updateCSSClassesForFolder(path, plugin); } -export function hideFolderNoteInFileExplorer(folderPath: string, plugin: FolderNotesPlugin) { +export function hideFolderNoteInFileExplorer(folderPath: string, plugin: FolderNotesPlugin): void { plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter( (folder) => (folder.path !== folderPath) && folder.showFolderNote); plugin.saveSettings(false); @@ -191,7 +232,7 @@ export function hideFolderNoteInFileExplorer(folderPath: string, plugin: FolderN updateCSSClassesForFolder(folderPath, plugin); } -export function setActiveFolder(folderPath: string, plugin: FolderNotesPlugin) { +export function setActiveFolder(folderPath: string, plugin: FolderNotesPlugin): void { const fileExplorerItem = getFileExplorerElement(folderPath, plugin); if (fileExplorerItem) { fileExplorerItem.addClass('fn-is-active'); @@ -199,7 +240,7 @@ export function setActiveFolder(folderPath: string, plugin: FolderNotesPlugin) { } } -export function removeActiveFolder(plugin: FolderNotesPlugin) { +export function removeActiveFolder(plugin: FolderNotesPlugin): void { if (plugin.activeFolderDom) { plugin.activeFolderDom.removeClass('fn-is-active'); plugin.activeFolderDom?.removeClass('has-focus'); diff --git a/src/functions/utils.ts b/src/functions/utils.ts index 468c5de..ec9f2ff 100644 --- a/src/functions/utils.ts +++ b/src/functions/utils.ts @@ -2,7 +2,7 @@ import { TFolder, TFile, View } from 'obsidian'; import type { FileExplorerWorkspaceLeaf, FileExplorerView } from 'src/globals'; import { getFolderNote } from './folderNoteFunctions'; import type FolderNotesPlugin from 'src/main'; -import type { FileExplorerLeaf } from 'obsidian-typings'; +import type { FileExplorerLeaf, FileTreeItem, TreeNode } from 'obsidian-typings'; import type FolderOverviewPlugin from 'src/obsidian-folder-overview/src/main'; export function getFileNameFromPathString(path: string): string { @@ -10,11 +10,12 @@ export function getFileNameFromPathString(path: string): string { } export function getFolderNameFromPathString(path: string): string { + const PARENT_FOLDER_INDEX = -2; + const LAST_FOLDER_INDEX = -1; if (path.endsWith('.md') || path.endsWith('.canvas')) { - return path.split('/').slice(-2)[0]; + return path.split('/').slice(PARENT_FOLDER_INDEX)[0]; } - return path.split('/').slice(-1)[0]; - + return path.split('/').slice(LAST_FOLDER_INDEX)[0]; } export function removeExtension(name: string): string { @@ -39,16 +40,20 @@ export function getParentFolderPath(path: string): string { return this.getFolderPathFromString(this.getFolderPathFromString(path)); } -export function getFileExplorer(plugin: FolderNotesPlugin | FolderOverviewPlugin) { - return plugin.app.workspace.getLeavesOfType('file-explorer')[0] as any as FileExplorerWorkspaceLeaf; +export function getFileExplorer( + plugin: FolderNotesPlugin | FolderOverviewPlugin, +): FileExplorerWorkspaceLeaf { + // eslint-disable-next-line max-len + const leaf = plugin.app.workspace.getLeavesOfType('file-explorer')[0] as unknown as FileExplorerWorkspaceLeaf; + return leaf; } -export function getFileExplorerView(plugin: FolderNotesPlugin) { +export function getFileExplorerView(plugin: FolderNotesPlugin): FileExplorerView { return getFileExplorer(plugin).view; } -export function getFocusedItem(plugin: FolderNotesPlugin) { - const fileExplorer = getFileExplorer(plugin) as any as FileExplorerLeaf; +export function getFocusedItem(plugin: FolderNotesPlugin): TreeNode | null { + const fileExplorer = getFileExplorer(plugin) as unknown as FileExplorerLeaf; const { focusedItem } = fileExplorer.view.tree; return focusedItem; } diff --git a/src/globals.d.ts b/src/globals.d.ts index 1229822..53fff77 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -40,7 +40,6 @@ interface FileItem { el: HTMLDivElement; file: TFile; fileExplorer: FileExplorerView; - info: any; selfEl: HTMLDivElement; innerEl: HTMLDivElement; } @@ -48,7 +47,6 @@ interface FileItem { interface FolderItem { el: HTMLDivElement; fileExplorer: FileExplorerView; - info: any; selfEl: HTMLDivElement; innerEl: HTMLDivElement; file: TFolder; diff --git a/src/main.ts b/src/main.ts index 6f18134..ee94694 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,13 +1,23 @@ - -import type { TAbstractFile, MarkdownPostProcessorContext, WorkspaceLeaf } from 'obsidian'; -import { Plugin, TFile, TFolder, parseYaml, Notice, Keymap, requireApiVersion, Platform, debounce } from 'obsidian'; -import type { FolderNotesSettings } from './settings/SettingsTab'; -import { DEFAULT_SETTINGS, SettingsTab } from './settings/SettingsTab'; +import { + type TAbstractFile, + type MarkdownPostProcessorContext, + type WorkspaceLeaf, + Plugin, TFile, TFolder, + parseYaml, Notice, Keymap, + requireApiVersion, Platform, debounce, +} from 'obsidian'; +import { + type FolderNotesSettings, DEFAULT_SETTINGS, SettingsTab, +} from './settings/SettingsTab'; import { Commands } from './Commands'; import type { FileExplorerWorkspaceLeaf } from './globals'; -import { registerFileExplorerObserver, unregisterFileExplorerObserver } from './events/MutationObserver'; +import { + registerFileExplorerObserver, unregisterFileExplorerObserver, +} from './events/MutationObserver'; import { handleRename } from './events/handleRename'; -import { getFolderNote, getFolder, openFolderNote, createFolderNote } from './functions/folderNoteFunctions'; +import { + getFolderNote, getFolder, openFolderNote, createFolderNote, +} from './functions/folderNoteFunctions'; import { handleCreate } from './events/handleCreate'; import { FrontMatterTitlePluginHandler } from './events/FrontMatterTitle'; import { FolderOverviewSettings } from './obsidian-folder-overview/src/modals/Settings'; @@ -15,10 +25,12 @@ import { FolderOverview } from './obsidian-folder-overview/src/FolderOverview'; import { TabManager } from './events/TabManager'; import './functions/ListComponent'; import { handleDelete } from './events/handleDelete'; -import { addCSSClassToFileExplorerEl, getFileExplorerElement, removeCSSClassFromFileExplorerEL, refreshAllFolderStyles, setActiveFolder, removeActiveFolder } from './functions/styleFunctions'; +import { + addCSSClassToFileExplorerEl, getFileExplorerElement, removeCSSClassFromFileExplorerEL, + refreshAllFolderStyles, setActiveFolder, removeActiveFolder, +} from './functions/styleFunctions'; import { getExcludedFolder } from './ExcludeFolders/functions/folderFunctions'; import type { FileExplorerView, InternalPlugin } from 'obsidian-typings'; -// import { getFocusedItem } from './functions/utils'; import { FOLDER_OVERVIEW_VIEW, FolderOverviewView } from './obsidian-folder-overview/src/view'; import { registerOverviewCommands } from './obsidian-folder-overview/src/Commands'; import { updateOverviewView, updateViewDropdown } from './obsidian-folder-overview/src/main'; @@ -26,7 +38,6 @@ import { FvIndexDB } from './obsidian-folder-overview/src/utils/IndexDB'; import { updateAllOverviews } from './obsidian-folder-overview/src/utils/functions'; export default class FolderNotesPlugin extends Plugin { - observer: MutationObserver; settings: FolderNotesSettings; settingsTab: SettingsTab; activeFolderDom: HTMLElement | null; @@ -43,7 +54,7 @@ export default class FolderNotesPlugin extends Plugin { private fileExplorerPlugin!: InternalPlugin; private fileExplorerView!: FileExplorerView; - async onload() { + async onload(): Promise { console.log('loading folder notes plugin'); await this.loadSettings(); this.settingsTab = new SettingsTab(this.app, this); @@ -54,17 +65,29 @@ export default class FolderNotesPlugin extends Plugin { // Add CSS Classes document.body.classList.add('folder-notes-plugin'); if (this.settings.hideFolderNote) { document.body.classList.add('hide-folder-note'); } - if (this.settings.hideCollapsingIconForEmptyFolders) { document.body.classList.add('fn-hide-empty-collapse-icon'); } + if (this.settings.hideCollapsingIconForEmptyFolders) { + document.body.classList.add('fn-hide-empty-collapse-icon'); + } if (this.settings.underlineFolder) { document.body.classList.add('folder-note-underline'); } if (this.settings.boldName) { document.body.classList.add('folder-note-bold'); } if (this.settings.cursiveName) { document.body.classList.add('folder-note-cursive'); } if (this.settings.boldNameInPath) { document.body.classList.add('folder-note-bold-path'); } - if (this.settings.cursiveNameInPath) { document.body.classList.add('folder-note-cursive-path'); } - if (this.settings.underlineFolderInPath) { document.body.classList.add('folder-note-underline-path'); } - if (this.settings.stopWhitespaceCollapsing) { document.body.classList.add('fn-whitespace-stop-collapsing'); } - if (this.settings.hideCollapsingIcon) { document.body.classList.add('fn-hide-collapse-icon'); } - if (!this.settings.highlightFolder) { document.body.classList.add('disable-folder-highlight'); } - // document.body.classList.add('fv-hide-link-list'); + if (this.settings.cursiveNameInPath) { + document.body.classList.add('folder-note-cursive-path'); + } + if (this.settings.underlineFolderInPath) { + document.body.classList.add('folder-note-underline-path'); + } + if (this.settings.stopWhitespaceCollapsing) { + document.body.classList.add('fn-whitespace-stop-collapsing'); + } + if (this.settings.hideCollapsingIcon) { + document.body.classList.add('fn-hide-collapse-icon'); + } + if (!this.settings.highlightFolder) { + document.body.classList.add('disable-folder-highlight'); + } + if (requireApiVersion('1.7.2')) { document.body.classList.add('version-1-7-2'); } @@ -74,23 +97,11 @@ export default class FolderNotesPlugin extends Plugin { this.app.workspace.onLayoutReady(this.onLayoutReady.bind(this)); - // this.observer.observe(document.body, { - // childList: true, - // subtree: true, - // }); - if (!this.settings.persistentSettingsTab.afterRestart) { this.settings.settingsTab = 'general'; } this.registerDomEvent(window, 'keydown', (event: KeyboardEvent) => { - // Was a bit too buggy - // if (event.key === 'Enter') { - // const folderNote = getFolderNote(this, getFocusedItem(this)?.file?.path || ''); - // if (!folderNote) return; - // openFolderNote(this, folderNote); - // } - const { hoveredElement } = this; if (this.hoverLinkTriggered) return; if (!hoveredElement) return; @@ -143,12 +154,15 @@ export default class FolderNotesPlugin extends Plugin { this.handleVaultChange(); })); - this.registerMarkdownCodeBlockProcessor('folder-overview', (source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) => { - this.handleOverviewBlock(source, el, ctx); - }); + this.registerMarkdownCodeBlockProcessor( + 'folder-overview', + (source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) => { + this.handleOverviewBlock(source, el, ctx); + }, + ); } - onLayoutReady() { + onLayoutReady(): void { if (!this._loaded) { return; } @@ -175,8 +189,9 @@ export default class FolderNotesPlugin extends Plugin { const fileExplorerPlugin = this.app.internalPlugins.getEnabledPluginById('file-explorer'); if (fileExplorerPlugin) { - const originalRevealInFolder = fileExplorerPlugin.revealInFolder.bind(fileExplorerPlugin); - fileExplorerPlugin.revealInFolder = (file: TAbstractFile) => { + const originalRevealInFolder = fileExplorerPlugin.revealInFolder + .bind(fileExplorerPlugin); + fileExplorerPlugin.revealInFolder = (file: TAbstractFile): void => { if (file instanceof TFile) { const folder = getFolder(this, file); if (folder instanceof TFolder) { @@ -186,9 +201,10 @@ export default class FolderNotesPlugin extends Plugin { } document.body.classList.remove('hide-folder-note'); originalRevealInFolder.call(fileExplorerPlugin, folder); + const FOLDER_REVEAL_DELAY = 100; setTimeout(() => { document.body.classList.add('hide-folder-note'); - }, 100); + }, FOLDER_REVEAL_DELAY); return; } } @@ -201,26 +217,29 @@ export default class FolderNotesPlugin extends Plugin { if (!view) { return; } - // @ts-ignore - const editMode = view.editMode ?? view.sourceMode ?? this.app.workspace.activeEditor?.editMode; + // @ts-expect-error use internal API + const editMode = view.editMode ?? view.sourceMode + // @ts-expect-error use internal API + ?? this.app.workspace.activeEditor?.editMode; const plugin = this; if (!editMode) { return; } - // @ts-ignore const clipboardProto = editMode.clipboardManager.constructor.prototype; const originalHandleDragOver = clipboardProto.handleDragOver; const originalHandleDrop = clipboardProto.handleDrop; - clipboardProto.handleDragOver = function (evt: DragEvent, ...args: any[]) { + clipboardProto.handleDragOver = function (evt: DragEvent, ...args: unknown[]): void { const { dragManager } = this.app; const draggable = dragManager?.draggable; if (draggable?.file instanceof TFolder) { const folderNote = getFolderNote(plugin, draggable.file.path); if (folderNote) { - dragManager.setAction(window.i18next.t('interface.drag-and-drop.insert-link-here')); + dragManager.setAction( + window.i18next.t('interface.drag-and-drop.insert-link-here'), + ); return; } } @@ -228,7 +247,7 @@ export default class FolderNotesPlugin extends Plugin { return originalHandleDragOver.call(this, evt, ...args); }; - clipboardProto.handleDrop = function (evt: DragEvent, ...args: any[]) { + clipboardProto.handleDrop = function (evt: DragEvent, ...args: unknown[]): void { const { dragManager } = this.app; const draggable = dragManager?.draggable; @@ -248,57 +267,35 @@ export default class FolderNotesPlugin extends Plugin { } } - handleVaultChange() { + handleVaultChange(): void { if (!this.settings.fvGlobalSettings.autoUpdateLinks) return; + const DEBOUNCE_DELAY = 2000; debounce(() => { updateAllOverviews(this); - }, 2000, true)(); + }, DEBOUNCE_DELAY, true)(); } - handleFileExplorerClick(evt: MouseEvent) { + handleFileExplorerClick(evt: MouseEvent): void { const target = evt.target as HTMLElement; if (evt.shiftKey) return; + if (this.isMobileClickDisabled()) return; - if (Platform.isMobile && this.settings.disableOpenFolderNoteOnClick) return; - - // Check if the click is on a folder - const folderTitleEl = target.closest('.nav-folder-title') as HTMLElement; + const { folderTitleEl, onlyClickedOnFolderTitle } = this.getFolderTitleInfo(target); if (!folderTitleEl) return; + if (this.shouldIgnoreClickByWhitespaceOrCollapse(target, onlyClickedOnFolderTitle)) return; - const onlyClickedOnFolderTitle = !!target.closest('.nav-folder-title-content'); - // const folderTitleContentEl = target.closest('.nav-folder-title-content') as HTMLElement; - // if (folderTitleContentEl) { - // const rect = folderTitleContentEl.getBoundingClientRect(); - // const clickOffsetX = evt.clientX - rect.left; - // // Ignore clicks within the first N pixels, e.g., 20px where the icon is displayed - // if (clickOffsetX < 20) return; - // } - if (!this.settings.stopWhitespaceCollapsing && !onlyClickedOnFolderTitle) return; - - // Ignore clicks on the collapse icon - if (target.closest('.collapse-icon')) return; - - const folderPath = folderTitleEl.getAttribute('data-path'); + const folderPath = this.getValidFolderPath(folderTitleEl); if (!folderPath) return; - const excludedFolder = getExcludedFolder(this, folderPath, true); - if (excludedFolder?.disableFolderNote) return; - - const usedCtrl = Platform.isMacOS ? evt.metaKey : evt.ctrlKey; - + const usedCtrl = this.isCtrlUsed(evt); const folderNote = getFolderNote(this, folderPath); - if (!folderNote && (evt.altKey || Keymap.isModEvent(evt) === 'tab')) { - if ((this.settings.altKey && evt.altKey) || (usedCtrl && this.settings.ctrlKey)) { - createFolderNote(this, folderPath, true, undefined, true); - addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, this); - removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, this); - return; - } + + if (!folderNote && this.shouldCreateNote(evt, usedCtrl)) { + this.createNoteAndMark(folderPath); + return; } if (!(folderNote instanceof TFile)) return; - - if (this.settings.openWithCtrl && !usedCtrl) return; - if (this.settings.openWithAlt && !evt.altKey) return; + if (!this.shouldOpenNote(usedCtrl, evt)) return; if (!this.settings.enableCollapsing || usedCtrl) { evt.preventDefault(); @@ -308,6 +305,58 @@ export default class FolderNotesPlugin extends Plugin { openFolderNote(this, folderNote, evt); } + private isMobileClickDisabled(): boolean { + return Platform.isMobile && this.settings.disableOpenFolderNoteOnClick; + } + + private getFolderTitleInfo(target: HTMLElement): { + folderTitleEl: HTMLElement | null; + onlyClickedOnFolderTitle: boolean; + } { + const folderTitleEl = target.closest('.nav-folder-title') as HTMLElement | null; + const onlyClickedOnFolderTitle = !!target.closest('.nav-folder-title-content'); + return { folderTitleEl, onlyClickedOnFolderTitle }; + } + + private shouldIgnoreClickByWhitespaceOrCollapse( + target: HTMLElement, + onlyClickedOnFolderTitle: boolean, + ): boolean { + if (!this.settings.stopWhitespaceCollapsing && !onlyClickedOnFolderTitle) return true; + if (target.closest('.collapse-icon')) return true; + return false; + } + + private getValidFolderPath(folderTitleEl: HTMLElement): string | null { + const folderPath = folderTitleEl.getAttribute('data-path'); + if (!folderPath) return null; + const excludedFolder = getExcludedFolder(this, folderPath, true); + if (excludedFolder?.disableFolderNote) return null; + return folderPath; + } + + private isCtrlUsed(evt: MouseEvent): boolean { + return Platform.isMacOS ? evt.metaKey : evt.ctrlKey; + } + + private shouldCreateNote(evt: MouseEvent, usedCtrl: boolean): boolean { + const isTabMod = Keymap.isModEvent(evt) === 'tab'; + if (!(evt.altKey || isTabMod)) return false; + return (this.settings.altKey && evt.altKey) || (usedCtrl && this.settings.ctrlKey); + } + + private createNoteAndMark(folderPath: string): void { + createFolderNote(this, folderPath, true, undefined, true); + addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, this); + removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, this); + } + + private shouldOpenNote(usedCtrl: boolean, evt: MouseEvent): boolean { + if (this.settings.openWithCtrl && !usedCtrl) return false; + if (this.settings.openWithAlt && !evt.altKey) return false; + return true; + } + handleOverviewBlock(source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext): void { const observer = new MutationObserver(() => { const editButton = el.parentElement?.childNodes.item(1); @@ -317,8 +366,12 @@ export default class FolderNotesPlugin extends Plugin { e.preventDefault(); e.stopPropagation(); new FolderOverviewSettings( - this.app, this, parseYaml(source), - ctx, el, this.settings.defaultOverview, + this.app, + this, + parseYaml(source), + ctx, + el, + this.settings.defaultOverview, ).open(); }, { capture: true }); } @@ -331,21 +384,35 @@ export default class FolderNotesPlugin extends Plugin { try { if (this.app.workspace.layoutReady) { - const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverview); + const { defaultOverview } = this.settings; + const folderOverview = new FolderOverview( + this, + ctx, + source, + el, + defaultOverview, + ); folderOverview.create(this, el, ctx); } else { this.app.workspace.onLayoutReady(() => { - const folderOverview = new FolderOverview(this, ctx, source, el, this.settings.defaultOverview); + const folderOverview = new FolderOverview( + this, + ctx, + source, + el, + this.settings.defaultOverview, + ); folderOverview.create(this, el, ctx); }); } } catch (e) { + // eslint-disable-next-line max-len new Notice('Error creating folder overview (folder notes plugin) - check console for more details'); console.error(e); } } - async activateOverviewView() { + async activateOverviewView(): Promise { const { workspace } = this.app; let leaf: WorkspaceLeaf | null = null; @@ -362,13 +429,14 @@ export default class FolderNotesPlugin extends Plugin { workspace.revealLeaf(leaf); } - updateOverviewView = updateOverviewView; - updateViewDropdown = updateViewDropdown; + updateOverviewView: typeof updateOverviewView = updateOverviewView; + updateViewDropdown: typeof updateViewDropdown = updateViewDropdown; isEmptyFolderNoteFolder(folder: TFolder): boolean { const attachmentFolderPath = this.app.vault.getConfig('attachmentFolderPath') as string; const cleanAttachmentFolderPath = attachmentFolderPath?.replace('./', '') || ''; - const attachmentsAreInRootFolder = attachmentFolderPath === './' || attachmentFolderPath === ''; + const attachmentsAreInRootFolder = attachmentFolderPath === './' + || attachmentFolderPath === ''; const threshold = this.settings.storageLocation === 'insideFolder' ? 1 : 0; if (folder.children.length === 0) { addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this); @@ -379,10 +447,13 @@ export default class FolderNotesPlugin extends Plugin { } else if (folder.children.length > threshold) { if (attachmentsAreInRootFolder) { return false; - } else if (this.settings.ignoreAttachmentFolder && this.app.vault.getAbstractFileByPath(`${folder.path}/${cleanAttachmentFolderPath}`)) { + } else if (this.settings.ignoreAttachmentFolder + && this.app.vault.getAbstractFileByPath( + `${folder.path}/${cleanAttachmentFolderPath}`)) { const folderPath = `${folder.path}/${cleanAttachmentFolderPath}`; const attachmentFolder = this.app.vault.getAbstractFileByPath(folderPath); - if (attachmentFolder instanceof TFolder && folder.children.length <= threshold + 1) { + if (attachmentFolder instanceof TFolder + && folder.children.length <= threshold + 1) { if (!folder.collapsed) { getFileExplorerElement(folder.path, this)?.click(); } @@ -395,13 +466,20 @@ export default class FolderNotesPlugin extends Plugin { return true; } - async changeFolderNameInExplorer(folder: TFolder, newName: string | null | undefined, waitForCreate = false, count = 0) { + async changeFolderNameInExplorer( + folder: TFolder, + newName: string | null | undefined, + waitForCreate = false, + count = 0, + ): Promise { + const MAX_RETRY_COUNT = 5; + const RETRY_DELAY_MS = 500; if (!newName) newName = folder.name; let fileExplorerItem = getFileExplorerElement(folder.path, this); if (!fileExplorerItem) { - if (waitForCreate && count < 5) { - await new Promise((r) => setTimeout(r, 500)); - this.changeFolderNameInExplorer(folder, newName, waitForCreate, count + 1); + if (waitForCreate && count < MAX_RETRY_COUNT) { + await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS)); + void this.changeFolderNameInExplorer(folder, newName, waitForCreate, count + 1); return; } return; @@ -410,15 +488,19 @@ export default class FolderNotesPlugin extends Plugin { fileExplorerItem = fileExplorerItem?.querySelector('div.nav-folder-title-content'); if (!fileExplorerItem) { return; } if (this.settings.frontMatterTitle.explorer && this.settings.frontMatterTitle.enabled) { - fileExplorerItem.innerText = newName; - fileExplorerItem.setAttribute('old-name', folder.name); + (fileExplorerItem as HTMLElement).innerText = newName; + (fileExplorerItem as HTMLElement).setAttribute('old-name', folder.name); } else { - fileExplorerItem.innerText = folder.name; - fileExplorerItem.removeAttribute('old-name'); + (fileExplorerItem as HTMLElement).innerText = folder.name; + (fileExplorerItem as HTMLElement).removeAttribute('old-name'); } } - async changeFolderNameInPath(folder: TFolder, newName: string | null | undefined, breadcrumb: HTMLElement) { + async changeFolderNameInPath( + folder: TFolder, + newName: string | null | undefined, + breadcrumb: HTMLElement, + ): Promise { if (!newName) newName = folder.name; breadcrumb.textContent = folder.newName || folder.name; @@ -429,7 +511,7 @@ export default class FolderNotesPlugin extends Plugin { /** * Updates all folder names in the path above the note editor */ - updateAllBreadcrumbs(remove?: boolean) { + updateAllBreadcrumbs(remove?: boolean): void { if (!this.settings.frontMatterTitle.path && !remove) { return; } const viewHeaderItems = document.querySelectorAll('span.view-header-breadcrumb'); const files = this.app.vault.getAllLoadedFiles().filter((file) => file instanceof TFolder); @@ -449,7 +531,7 @@ export default class FolderNotesPlugin extends Plugin { }); } - onunload() { + onunload(): void { unregisterFileExplorerObserver(); document.body.classList.remove('folder-notes-plugin'); document.body.classList.remove('folder-note-underline'); @@ -461,7 +543,7 @@ export default class FolderNotesPlugin extends Plugin { } } - async loadSettings() { + async loadSettings(): Promise { const data = await this.loadData(); if (data) { if (data.allowWhitespaceCollapsing === true) { @@ -479,12 +561,14 @@ export default class FolderNotesPlugin extends Plugin { } if (!data) { return; } - const overview = (data as any).defaultOverview; + const overview = data.defaultOverview; if (!overview) { return; } - this.settings.defaultOverview = Object.assign({}, DEFAULT_SETTINGS.defaultOverview, overview); + this.settings.defaultOverview = Object.assign( + {}, DEFAULT_SETTINGS.defaultOverview, overview, + ); } - async saveSettings(reloadStyles?: boolean) { + async saveSettings(reloadStyles?: boolean): Promise { await this.saveData(this.settings); // cleanup any css if we need too if ((!this.settingsOpened || reloadStyles === true) && reloadStyles !== false) { diff --git a/src/modals/AddSupportedFileType.ts b/src/modals/AddSupportedFileType.ts index c4e802d..787f4e1 100644 --- a/src/modals/AddSupportedFileType.ts +++ b/src/modals/AddSupportedFileType.ts @@ -1,5 +1,4 @@ -import type { App, SettingTab } from 'obsidian'; -import { Modal, Setting, Notice } from 'obsidian'; +import { Modal, Setting, Notice, type App, type SettingTab } from 'obsidian'; import type FolderNotesPlugin from '../main'; import type { ListComponent } from 'src/functions/ListComponent'; @@ -17,7 +16,8 @@ export default class AddSupportedFileModal extends Modal { this.list = list; this.settingsTab = settingsTab; } - onOpen() { + + onOpen(): void { const { contentEl } = this; // close when user presses enter contentEl.addEventListener('keydown', (e) => { @@ -38,7 +38,7 @@ export default class AddSupportedFileModal extends Modal { }), ); } - async onClose() { + async onClose(): Promise { if (this.name.toLocaleLowerCase() === 'markdown') { this.name = 'md'; } @@ -47,9 +47,9 @@ export default class AddSupportedFileModal extends Modal { contentEl.empty(); this.settingsTab.display(); } else if (this.plugin.settings.supportedFileTypes.includes(this.name.toLowerCase())) { - return new Notice('This extension is already supported'); + new Notice('This extension is already supported'); + return; } else { - // @ts-ignore await this.list.addValue(this.name.toLowerCase()); this.settingsTab.display(); this.plugin.saveSettings(); diff --git a/src/modals/AskForExtension.ts b/src/modals/AskForExtension.ts index 50b5ee8..7acd569 100644 --- a/src/modals/AskForExtension.ts +++ b/src/modals/AskForExtension.ts @@ -1,5 +1,4 @@ -import type { TFile } from 'obsidian'; -import { FuzzySuggestModal } from 'obsidian'; +import { FuzzySuggestModal, type TFile } from 'obsidian'; import type FolderNotesPlugin from 'src/main'; import { createFolderNote } from 'src/functions/folderNoteFunctions'; export class AskForExtensionModal extends FuzzySuggestModal { @@ -9,7 +8,14 @@ export class AskForExtensionModal extends FuzzySuggestModal { openFile: boolean; useModal: boolean | undefined; existingNote: TFile | undefined; - constructor(plugin: FolderNotesPlugin, folderPath: string, openFile: boolean, extension: string, useModal?: boolean, existingNote?: TFile) { + constructor( + plugin: FolderNotesPlugin, + folderPath: string, + openFile: boolean, + extension: string, + useModal?: boolean, + existingNote?: TFile, + ) { super(plugin.app); this.plugin = plugin; this.folderPath = folderPath; @@ -21,17 +27,26 @@ export class AskForExtensionModal extends FuzzySuggestModal { } getItems(): string[] { - return this.plugin.settings.supportedFileTypes.filter((item) => item.toLowerCase() !== '.ask'); + return this.plugin.settings.supportedFileTypes.filter( + (item) => item.toLowerCase() !== '.ask', + ); } getItemText(item: string): string { return item; } - onChooseItem(item: string, evt: MouseEvent | KeyboardEvent) { + onChooseItem(item: string, _evt: MouseEvent | KeyboardEvent): void { this.plugin.askModalCurrentlyOpen = false; this.extension = '.' + item; - createFolderNote(this.plugin, this.folderPath, this.openFile, this.extension, this.useModal, this.existingNote); + createFolderNote( + this.plugin, + this.folderPath, + this.openFile, + this.extension, + this.useModal, + this.existingNote, + ); this.close(); } } diff --git a/src/modals/DeleteConfirmation.ts b/src/modals/DeleteConfirmation.ts index c179ec4..ac857b6 100644 --- a/src/modals/DeleteConfirmation.ts +++ b/src/modals/DeleteConfirmation.ts @@ -1,5 +1,4 @@ -import type { App, TFile } from 'obsidian'; -import { Modal, Platform } from 'obsidian'; +import { Modal, Platform, type App, type TFile } from 'obsidian'; import type FolderNotesPlugin from '../main'; import { deleteFolderNote } from 'src/functions/folderNoteFunctions'; export default class DeleteConfirmationModal extends Modal { @@ -12,21 +11,25 @@ export default class DeleteConfirmationModal extends Modal { this.app = app; this.file = file; } - onOpen() { + onOpen(): void { const { contentEl, plugin } = this; const modalTitle = contentEl.createDiv({ cls: 'fn-modal-title' }); const modalContent = contentEl.createDiv({ cls: 'fn-modal-content' }); modalTitle.createEl('h2', { text: 'Delete folder note' }); + // eslint-disable-next-line max-len modalContent.createEl('p', { text: `Are you sure you want to delete the folder note '${this.file.name}' ?` }); switch (plugin.settings.deleteFilesAction) { case 'trash': modalContent.createEl('p', { text: 'It will be moved to your system trash.' }); break; case 'obsidianTrash': + // eslint-disable-next-line max-len modalContent.createEl('p', { text: 'It will be moved to your Obsidian trash, which is located in the ".trash" hidden folder in your vault.' }); break; case 'delete': - modalContent.createEl('p', { text: 'It will be permanently deleted.' }).setCssStyles({ color: 'red' }); + modalContent + .createEl('p', { text: 'It will be permanently deleted.' }) + .setCssStyles({ color: 'red' }); break; } @@ -47,7 +50,10 @@ export default class DeleteConfirmationModal extends Modal { plugin.saveSettings(); }); } else { - const confirmButton = buttonContainer.createEl('button', { text: 'Delete and don\'t ask again', cls: 'mod-destructive' }); + const confirmButton = buttonContainer.createEl('button', { + text: 'Delete and don\'t ask again', + cls: 'mod-destructive', + }); confirmButton.addEventListener('click', async () => { plugin.settings.showDeleteConfirmation = false; plugin.saveSettings(); @@ -56,19 +62,25 @@ export default class DeleteConfirmationModal extends Modal { }); } - const deleteButton = buttonContainer.createEl('button', { text: 'Delete', cls: 'mod-warning' }); + const deleteButton = buttonContainer.createEl('button', { + text: 'Delete', + cls: 'mod-warning', + }); deleteButton.addEventListener('click', async () => { this.close(); deleteFolderNote(plugin, this.file, false); }); deleteButton.focus(); - const cancelButton = buttonContainer.createEl('button', { text: 'Cancel', cls: 'mod-cancel' }); + const cancelButton = buttonContainer.createEl('button', { + text: 'Cancel', + cls: 'mod-cancel', + }); cancelButton.addEventListener('click', async () => { this.close(); }); } - onClose() { + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/modals/ExistingNote.ts b/src/modals/ExistingNote.ts index d3c680c..95ac4da 100644 --- a/src/modals/ExistingNote.ts +++ b/src/modals/ExistingNote.ts @@ -1,5 +1,12 @@ -import type { App, TFile, TFolder, TAbstractFile } from 'obsidian'; -import { Modal, Setting, Platform } from 'obsidian'; +import { + Modal, + Setting, + Platform, + type App, + type TFile, + type TFolder, + type TAbstractFile, +} from 'obsidian'; import type FolderNotesPlugin from '../main'; import { turnIntoFolderNote } from 'src/functions/folderNoteFunctions'; export default class ExistingFolderNoteModal extends Modal { @@ -8,7 +15,13 @@ export default class ExistingFolderNoteModal extends Modal { file: TFile; folder: TFolder; folderNote: TAbstractFile; - constructor(app: App, plugin: FolderNotesPlugin, file: TFile, folder: TFolder, folderNote: TAbstractFile) { + constructor( + app: App, + plugin: FolderNotesPlugin, + file: TFile, + folder: TFolder, + folderNote: TAbstractFile, + ) { super(app); this.plugin = plugin; this.app = app; @@ -16,18 +29,22 @@ export default class ExistingFolderNoteModal extends Modal { this.folder = folder; this.folderNote = folderNote; } - onOpen() { + onOpen(): void { const { contentEl } = this; contentEl.createEl('h2', { text: 'A folder note for this folder already exists' }); const setting = new Setting(contentEl); + // eslint-disable-next-line max-len setting.infoEl.createEl('p', { text: 'Are you sure you want to turn the note into a folder note and rename the existing folder note?' }); setting.infoEl.parentElement?.classList.add('fn-delete-confirmation-modal'); // Create a container for the buttons and the checkbox + // eslint-disable-next-line max-len const buttonContainer = setting.infoEl.createEl('div', { cls: 'fn-delete-confirmation-modal-buttons' }); if (Platform.isMobileApp) { - const confirmButton = buttonContainer.createEl('button', { text: 'Rename and don\'t ask again' }); + const confirmButton = buttonContainer.createEl('button', { + text: 'Rename and don\'t ask again', + }); confirmButton.classList.add('mod-warning', 'fn-confirmation-modal-button'); confirmButton.addEventListener('click', async () => { this.plugin.settings.showRenameConfirmation = false; @@ -64,7 +81,7 @@ export default class ExistingFolderNoteModal extends Modal { }); } - onClose() { + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/modals/FolderName.ts b/src/modals/FolderName.ts index bdef456..b50cf57 100644 --- a/src/modals/FolderName.ts +++ b/src/modals/FolderName.ts @@ -1,5 +1,4 @@ -import type { App, TFolder } from 'obsidian'; -import { Modal, Setting } from 'obsidian'; +import { Modal, Setting, type App, type TFolder } from 'obsidian'; import type FolderNotesPlugin from '../main'; export default class FolderNameModal extends Modal { plugin: FolderNotesPlugin; @@ -11,7 +10,8 @@ export default class FolderNameModal extends Modal { this.app = app; this.folder = folder; } - onOpen() { + + onOpen(): void { const { contentEl } = this; // close when user presses enter contentEl.addEventListener('keydown', (e) => { @@ -27,14 +27,25 @@ export default class FolderNameModal extends Modal { .setValue(this.folder.name.replace(this.plugin.settings.folderNoteType, '')) .onChange(async (value) => { if (value.trim() !== '') { - if (!this.app.vault.getAbstractFileByPath(this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + value.trim())) { - this.plugin.app.fileManager.renameFile(this.folder, this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + value.trim()); + const parentPath = this.folder.path.slice( + 0, + this.folder.path.lastIndexOf('/') + 1, + ); + const newFolderPath = parentPath + value.trim(); + if ( + !this.app.vault.getAbstractFileByPath(newFolderPath) + ) { + this.plugin.app.fileManager.renameFile( + this.folder, + newFolderPath, + ); } } }), ); } - onClose() { + + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/modals/NewFolderName.ts b/src/modals/NewFolderName.ts index 64fa454..8ecb63f 100644 --- a/src/modals/NewFolderName.ts +++ b/src/modals/NewFolderName.ts @@ -1,5 +1,4 @@ -import type { App, TFolder } from 'obsidian'; -import { Modal } from 'obsidian'; +import { Modal, type App, type TFolder } from 'obsidian'; import type FolderNotesPlugin from '../main'; export default class NewFolderNameModal extends Modal { plugin: FolderNotesPlugin; @@ -11,7 +10,8 @@ export default class NewFolderNameModal extends Modal { this.app = app; this.folder = folder; } - onOpen() { + + onOpen(): void { const { contentEl } = this; contentEl.addEventListener('keydown', (e) => { @@ -37,7 +37,7 @@ export default class NewFolderNameModal extends Modal { }, }); - textarea.addEventListener('focus', function() { + textarea.addEventListener('focus', function () { this.select(); }); @@ -50,23 +50,32 @@ export default class NewFolderNameModal extends Modal { this.close(); }); - const cancelButton = buttonContainer.createEl('button', { text: 'Cancel', cls: 'mod-cancel' }); + const cancelButton = buttonContainer.createEl('button', { + text: 'Cancel', + cls: 'mod-cancel', + }); cancelButton.addEventListener('click', () => { this.close(); }); } - onClose() { + + onClose(): void { const { contentEl } = this; contentEl.empty(); } - saveFolderName() { + saveFolderName(): void { const textarea = this.contentEl.querySelector('textarea'); if (textarea) { const newName = textarea.value.trim(); if (newName.trim() !== '') { - if (!this.app.vault.getAbstractFileByPath(this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + newName.trim())) { - this.plugin.app.fileManager.renameFile(this.folder, this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + newName.trim()); + const folderBasePath = this.folder.path.slice( + 0, + this.folder.path.lastIndexOf('/') + 1, + ); + const newFolderPath = folderBasePath + newName.trim(); + if (!this.app.vault.getAbstractFileByPath(newFolderPath)) { + this.plugin.app.fileManager.renameFile(this.folder, newFolderPath); } } } diff --git a/src/settings/ExcludedFoldersSettings.ts b/src/settings/ExcludedFoldersSettings.ts index e4126fb..b8b9345 100644 --- a/src/settings/ExcludedFoldersSettings.ts +++ b/src/settings/ExcludedFoldersSettings.ts @@ -1,4 +1,7 @@ -import { addExcludeFolderListItem, addExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; +import { + addExcludeFolderListItem, + addExcludedFolder, +} from 'src/ExcludeFolders/functions/folderFunctions'; import { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; import { addExcludePatternListItem } from 'src/ExcludeFolders/functions/patternFunctions'; import { Setting } from 'obsidian'; @@ -8,7 +11,7 @@ import PatternSettings from 'src/ExcludeFolders/modals/PatternSettings'; import WhitelistedFoldersSettings from 'src/ExcludeFolders/modals/WhitelistedFoldersSettings'; // import ExcludedFoldersWhitelist from 'src/ExcludeFolders/modals/WhitelistModal'; -export async function renderExcludeFolders(settingsTab: SettingsTab) { +export async function renderExcludeFolders(settingsTab: SettingsTab): Promise { const containerEl = settingsTab.settingsPage; const manageExcluded = new Setting(containerEl) .setHeading() @@ -25,9 +28,12 @@ export async function renderExcludeFolders(settingsTab: SettingsTab) { 'Use * after the folder name to exclude folders that start with the folder name.', ); manageExcluded.setDesc(desc3); + // eslint-disable-next-line max-len manageExcluded.infoEl.appendText('The regexes and wildcards are only for the folder name, not the path.'); manageExcluded.infoEl.createEl('br'); + // eslint-disable-next-line max-len manageExcluded.infoEl.appendText('If you want to switch to a folder path delete the pattern first.'); + // eslint-disable-next-line max-len manageExcluded.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; @@ -48,7 +54,11 @@ export async function renderExcludeFolders(settingsTab: SettingsTab) { cb.setButtonText('Manage'); cb.setCta(); cb.onClick(async () => { - new ExcludedFolderSettings(settingsTab.app, settingsTab.plugin, settingsTab.plugin.settings.excludeFolderDefaultSettings).open(); + new ExcludedFolderSettings( + settingsTab.app, + settingsTab.plugin, + settingsTab.plugin.settings.excludeFolderDefaultSettings, + ).open(); }); }); @@ -58,7 +68,11 @@ export async function renderExcludeFolders(settingsTab: SettingsTab) { cb.setButtonText('Manage'); cb.setCta(); cb.onClick(async () => { - new PatternSettings(settingsTab.app, settingsTab.plugin, settingsTab.plugin.settings.excludePatternDefaultSettings).open(); + new PatternSettings( + settingsTab.app, + settingsTab.plugin, + settingsTab.plugin.settings.excludePatternDefaultSettings, + ).open(); }); }); @@ -71,18 +85,29 @@ export async function renderExcludeFolders(settingsTab: SettingsTab) { cb.setClass('add-exclude-folder'); cb.setTooltip('Add excluded folder'); cb.onClick(() => { - const excludedFolder = new ExcludedFolder('', settingsTab.plugin.settings.excludeFolders.length, undefined, settingsTab.plugin); + const excludedFolder = new ExcludedFolder( + '', + settingsTab.plugin.settings.excludeFolders.length, + undefined, + settingsTab.plugin, + ); addExcludeFolderListItem(settingsTab, containerEl, excludedFolder); addExcludedFolder(settingsTab.plugin, excludedFolder); settingsTab.display(); }); }); - settingsTab.plugin.settings.excludeFolders.filter((folder) => !folder.hideInSettings).sort((a, b) => a.position - b.position).forEach((excludedFolder) => { - if (excludedFolder.string?.trim() !== '' && excludedFolder.path?.trim() === '') { - addExcludePatternListItem(settingsTab, containerEl, excludedFolder); - } else { - addExcludeFolderListItem(settingsTab, containerEl, excludedFolder); - } - }); + settingsTab.plugin.settings.excludeFolders + .filter((folder) => !folder.hideInSettings) + .sort((a, b) => a.position - b.position) + .forEach((excludedFolder) => { + if ( + excludedFolder.string?.trim() !== '' && + excludedFolder.path?.trim() === '' + ) { + addExcludePatternListItem(settingsTab, containerEl, excludedFolder); + } else { + addExcludeFolderListItem(settingsTab, containerEl, excludedFolder); + } + }); } diff --git a/src/settings/FileExplorerSettings.ts b/src/settings/FileExplorerSettings.ts index 0d79841..c69e620 100644 --- a/src/settings/FileExplorerSettings.ts +++ b/src/settings/FileExplorerSettings.ts @@ -1,6 +1,7 @@ +/* eslint-disable max-len */ import { Setting } from 'obsidian'; import type { SettingsTab } from './SettingsTab'; -export async function renderFileExplorer(settingsTab: SettingsTab) { +export async function renderFileExplorer(settingsTab: SettingsTab): Promise { const containerEl = settingsTab.settingsPage; new Setting(containerEl) @@ -34,7 +35,8 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { ); setting2.infoEl.appendText('Requires a restart to take effect'); - setting2.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; + const setting2AccentColor = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; + setting2.infoEl.style.color = setting2AccentColor; new Setting(containerEl) .setName('Open folder notes by only clicking directly on the folder name') @@ -65,7 +67,8 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { }), ); disableSetting.infoEl.appendText('Requires a restart to take effect'); - disableSetting.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; + const accentColor = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed'; + disableSetting.infoEl.style.color = accentColor; new Setting(containerEl) .setName('Use submenus') @@ -91,7 +94,15 @@ export async function renderFileExplorer(settingsTab: SettingsTab) { settingsTab.plugin.settings.frontMatterTitle.explorer = value; await settingsTab.plugin.saveSettings(); settingsTab.plugin.app.vault.getFiles().forEach((file) => { - settingsTab.plugin.fmtpHandler?.fmptUpdateFileName({ id: '', result: false, path: file.path, pathOnly: false }, false); + settingsTab.plugin.fmtpHandler?.fmptUpdateFileName( + { + id: '', + result: false, + path: file.path, + pathOnly: false, + }, + false, + ); }); }), ); diff --git a/src/settings/FolderOverviewSettings.ts b/src/settings/FolderOverviewSettings.ts index 310fb1e..de253e3 100644 --- a/src/settings/FolderOverviewSettings.ts +++ b/src/settings/FolderOverviewSettings.ts @@ -2,7 +2,7 @@ import { Setting } from 'obsidian'; import type { SettingsTab } from './SettingsTab'; import { createOverviewSettings } from 'src/obsidian-folder-overview/src/settings'; -export async function renderFolderOverview(settingsTab: SettingsTab) { +export async function renderFolderOverview(settingsTab: SettingsTab): Promise { const { plugin } = settingsTab; const defaultOverviewSettings = plugin.settings.defaultOverview; const containerEl = settingsTab.settingsPage; @@ -10,6 +10,7 @@ export async function renderFolderOverview(settingsTab: SettingsTab) { containerEl.createEl('h3', { text: 'Global settings' }); new Setting(containerEl) .setName('Auto-update links without opening the overview') + // eslint-disable-next-line max-len .setDesc('If enabled, the links that appear in the graph view will be updated even when you don\'t have the overview open somewhere.') .addToggle((toggle) => toggle @@ -35,5 +36,15 @@ export async function renderFolderOverview(settingsTab: SettingsTab) { span.setAttr('style', `color: ${accentColor};`); pEl.appendChild(span); - createOverviewSettings(containerEl, defaultOverviewSettings, plugin, plugin.settings.defaultOverview, settingsTab.display, undefined, undefined, undefined, settingsTab); + createOverviewSettings( + containerEl, + defaultOverviewSettings, + plugin, + plugin.settings.defaultOverview, + settingsTab.display, + undefined, + undefined, + undefined, + settingsTab, + ); } diff --git a/src/settings/GeneralSettings.ts b/src/settings/GeneralSettings.ts index 3a15b8e..27b026a 100644 --- a/src/settings/GeneralSettings.ts +++ b/src/settings/GeneralSettings.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ import { Setting, Platform } from 'obsidian'; import type { SettingsTab } from './SettingsTab'; import { ListComponent } from '../functions/ListComponent'; @@ -11,7 +12,8 @@ import RenameFolderNotesModal from './modals/RenameFns'; let debounceTimer: NodeJS.Timeout; -export async function renderGeneral(settingsTab: SettingsTab) { +// eslint-disable-next-line complexity +export async function renderGeneral(settingsTab: SettingsTab): Promise { const containerEl = settingsTab.settingsPage; const nameSetting = new Setting(containerEl) .setName('Folder note name template') @@ -25,6 +27,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { await settingsTab.plugin.saveSettings(); clearTimeout(debounceTimer); + const FOLDER_NOTE_NAME_DEBOUNCE_MS = 2000; debounceTimer = setTimeout(() => { if (!value.includes('{{folder_name}}')) { if (!settingsTab.showFolderNameInTabTitleSetting) { @@ -37,7 +40,7 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.showFolderNameInTabTitleSetting = false; } } - }, 2000); + }, FOLDER_NOTE_NAME_DEBOUNCE_MS); }), ) .addButton((button) => @@ -91,13 +94,24 @@ export async function renderGeneral(settingsTab: SettingsTab) { } }); - if (!settingsTab.plugin.settings.supportedFileTypes.includes(settingsTab.plugin.settings.folderNoteType.replace('.', '')) && settingsTab.plugin.settings.folderNoteType !== '.ask') { + if ( + !settingsTab.plugin.settings.supportedFileTypes.includes( + settingsTab.plugin.settings.folderNoteType.replace('.', ''), + ) && + settingsTab.plugin.settings.folderNoteType !== '.ask' + ) { settingsTab.plugin.settings.folderNoteType = '.md'; settingsTab.plugin.saveSettings(); } - let defaultType = settingsTab.plugin.settings.folderNoteType.startsWith('.') ? settingsTab.plugin.settings.folderNoteType : '.' + settingsTab.plugin.settings.folderNoteType; - if (!settingsTab.plugin.settings.supportedFileTypes.includes(defaultType.replace('.', ''))) { + let defaultType = settingsTab.plugin.settings.folderNoteType.startsWith('.') + ? settingsTab.plugin.settings.folderNoteType + : '.' + settingsTab.plugin.settings.folderNoteType; + if ( + !settingsTab.plugin.settings.supportedFileTypes.includes( + defaultType.replace('.', ''), + ) + ) { defaultType = '.ask'; settingsTab.plugin.settings.folderNoteType = defaultType; } @@ -118,14 +132,22 @@ export async function renderGeneral(settingsTab: SettingsTab) { 'Specify which file types are allowed as folder notes. Applies to both new and existing folders. Adding many types may affect performance.', ); setting0.setDesc(desc0); - const list = new ListComponent(setting0.settingEl, settingsTab.plugin.settings.supportedFileTypes || [], ['md', 'canvas']); + const list = new ListComponent( + setting0.settingEl, + settingsTab.plugin.settings.supportedFileTypes || [], + ['md', 'canvas'], + ); list.on('update', async (values: string[]) => { settingsTab.plugin.settings.supportedFileTypes = values; await settingsTab.plugin.saveSettings(); settingsTab.display(); }); - if (!settingsTab.plugin.settings.supportedFileTypes.includes('md') || !settingsTab.plugin.settings.supportedFileTypes.includes('canvas') || !settingsTab.plugin.settings.supportedFileTypes.includes('excalidraw')) { + if ( + !settingsTab.plugin.settings.supportedFileTypes.includes('md') || + !settingsTab.plugin.settings.supportedFileTypes.includes('canvas') || + !settingsTab.plugin.settings.supportedFileTypes.includes('excalidraw') + ) { setting0.addDropdown((dropdown) => { const options = [ { value: 'md', label: 'Markdown' }, @@ -144,7 +166,12 @@ export async function renderGeneral(settingsTab: SettingsTab) { dropdown.setValue('+'); dropdown.onChange(async (value) => { if (value === 'custom') { - return new AddSupportedFileModal(settingsTab.app, settingsTab.plugin, settingsTab, list as ListComponent).open(); + return new AddSupportedFileModal( + settingsTab.app, + settingsTab.plugin, + settingsTab, + list as ListComponent, + ).open(); } await list.addValue(value.toLowerCase()); settingsTab.display(); @@ -157,7 +184,12 @@ export async function renderGeneral(settingsTab: SettingsTab) { .setButtonText('Add custom file type') .setCta() .onClick(async () => { - new AddSupportedFileModal(settingsTab.app, settingsTab.plugin, settingsTab, list as ListComponent).open(); + new AddSupportedFileModal( + settingsTab.app, + settingsTab.plugin, + settingsTab, + list as ListComponent, + ).open(); }), ); } @@ -169,7 +201,11 @@ export async function renderGeneral(settingsTab: SettingsTab) { .addSearch((cb) => { new TemplateSuggest(cb.inputEl, settingsTab.plugin); cb.setPlaceholder('Template path'); - cb.setValue(settingsTab.plugin.app.vault.getAbstractFileByPath(settingsTab.plugin.settings.templatePath)?.name.replace('.md', '') || ''); + const templateFile = settingsTab.plugin.app.vault.getAbstractFileByPath( + settingsTab.plugin.settings.templatePath, + ); + const templateName = templateFile?.name.replace('.md', '') || ''; + cb.setValue(templateName); cb.onChange(async (value) => { if (value.trim() === '') { settingsTab.plugin.settings.templatePath = ''; @@ -464,16 +500,26 @@ export async function renderGeneral(settingsTab: SettingsTab) { settingsTab.plugin.settings.frontMatterTitle.enabled = value; await settingsTab.plugin.saveSettings(); if (value) { - settingsTab.plugin.fmtpHandler = new FrontMatterTitlePluginHandler(settingsTab.plugin); + settingsTab.plugin.fmtpHandler = + new FrontMatterTitlePluginHandler(settingsTab.plugin); } else { if (settingsTab.plugin.fmtpHandler) { settingsTab.plugin.updateAllBreadcrumbs(true); } settingsTab.plugin.app.vault.getFiles().forEach((file) => { - settingsTab.plugin.fmtpHandler?.fmptUpdateFileName({ id: '', result: false, path: file.path, pathOnly: false }, false); + settingsTab.plugin.fmtpHandler?.fmptUpdateFileName( + { + id: '', + result: false, + path: file.path, + pathOnly: false, + }, + false, + ); }); settingsTab.plugin.fmtpHandler?.deleteEvent(); - settingsTab.plugin.fmtpHandler = new FrontMatterTitlePluginHandler(settingsTab.plugin); + settingsTab.plugin.fmtpHandler = + new FrontMatterTitlePluginHandler(settingsTab.plugin); } settingsTab.display(); }), diff --git a/src/settings/PathSettings.ts b/src/settings/PathSettings.ts index 3ea8be2..034b1ed 100644 --- a/src/settings/PathSettings.ts +++ b/src/settings/PathSettings.ts @@ -1,6 +1,7 @@ +/* eslint-disable max-len */ import { Setting } from 'obsidian'; import type { SettingsTab } from './SettingsTab'; -export async function renderPath(settingsTab: SettingsTab) { +export async function renderPath(settingsTab: SettingsTab): Promise { const containerEl = settingsTab.settingsPage; new Setting(containerEl) .setName('Open folder note through path') diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index e6723c8..2eeb650 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -1,5 +1,7 @@ -import type { App, MarkdownPostProcessorContext } from 'obsidian'; -import { Notice, PluginSettingTab, TFile, TFolder } from 'obsidian'; +import { + Notice, PluginSettingTab, TFile, + TFolder, type App, type MarkdownPostProcessorContext, +} from 'obsidian'; import type FolderNotesPlugin from '../main'; import type { ExcludePattern } from 'src/ExcludeFolders/ExcludePattern'; import type { ExcludedFolder } from 'src/ExcludeFolders/ExcludeFolder'; @@ -236,7 +238,8 @@ export class SettingsTab extends PluginSettingTab { id: 'path', }, }; - renderSettingsPage(tabId: string) { + + renderSettingsPage(tabId: string): void { this.settingsPage.empty(); switch (tabId.toLocaleLowerCase()) { case this.TABS.GENERAL.id: @@ -257,7 +260,17 @@ export class SettingsTab extends PluginSettingTab { } } - display(contentEl?: HTMLElement, yaml?: defaultOverviewSettings, plugin?: FolderNotesPlugin, defaultSettings?: boolean, display?: CallableFunction, el?: HTMLElement, ctx?: MarkdownPostProcessorContext, file?: TFile | null, settingsTab?: this) { + display( + contentEl?: HTMLElement, + yaml?: defaultOverviewSettings, + plugin?: FolderNotesPlugin, + defaultSettings?: boolean, + display?: CallableFunction, + el?: HTMLElement, + ctx?: MarkdownPostProcessorContext, + file?: TFile | null, + settingsTab?: this, + ): void { plugin = this?.plugin ?? plugin; if (plugin) { plugin.settingsOpened = true; @@ -274,13 +287,17 @@ export class SettingsTab extends PluginSettingTab { for (const [tabId, tabInfo] of Object.entries(settingsTab.TABS)) { const tabEl = tabBar.createEl('div', { cls: 'fn-settings-tab' }); tabEl.createEl('div', { cls: 'fn-settings-tab-name', text: tabInfo.name }); - if (plugin && plugin.settings.settingsTab.toLocaleLowerCase() === tabId.toLocaleLowerCase()) { + if ( + plugin && + plugin.settings.settingsTab.toLocaleLowerCase() === + tabId.toLocaleLowerCase() + ) { tabEl.addClass('fn-settings-tab-active'); } tabEl.addEventListener('click', () => { - // @ts-ignore - for (const tabEl of tabBar.children) { - tabEl.removeClass('fn-settings-tab-active'); + // @ts-expect-error: tabBar.children may not have removeClass method, but we know it works in this context + for (const child of tabBar.children) { + child.removeClass('fn-settings-tab-active'); if (!plugin) { return; } plugin.settings.settingsTab = tabId.toLocaleLowerCase(); plugin.saveSettings(); @@ -300,23 +317,31 @@ export class SettingsTab extends PluginSettingTab { } } - renameFolderNotes() { + renameFolderNotes(): void { new Notice('Starting to update folder notes...'); const oldTemplate = this.plugin.settings.oldFolderNoteName ?? '{{folder_name}}'; for (const folder of this.app.vault.getAllLoadedFiles()) { if (folder instanceof TFolder) { - const folderNote = getFolderNote(this.plugin, folder.path, undefined, undefined, oldTemplate); + const folderNote = getFolderNote( + this.plugin, + folder.path, + undefined, + undefined, + oldTemplate, + ); if (!(folderNote instanceof TFile)) { continue; } const folderName = extractFolderName(oldTemplate, folderNote.basename) ?? ''; - const newFolderNoteName = this.plugin.settings.folderNoteName.replace('{{folder_name}}', folderName); + const newFolderNoteName = this.plugin.settings.folderNoteName + .replace('{{folder_name}}', folderName); let newPath = ''; if (this.plugin.settings.storageLocation === 'parentFolder') { if (getFolderPathFromString(folder.path).trim() === '/') { newPath = `${newFolderNoteName}.${folderNote.extension}`; } else { + // eslint-disable-next-line max-len newPath = `${folderNote.parent?.path}/${newFolderNoteName}.${folderNote.extension}`; } } else if (this.plugin.settings.storageLocation === 'insideFolder') { @@ -332,7 +357,7 @@ export class SettingsTab extends PluginSettingTab { new Notice('Finished updating folder notes'); } - switchStorageLocation(oldMethod: string) { + switchStorageLocation(oldMethod: string): void { new Notice('Starting to switch storage location...'); this.app.vault.getAllLoadedFiles().forEach((file) => { if (file instanceof TFolder) { diff --git a/src/settings/modals/BackupWarning.ts b/src/settings/modals/BackupWarning.ts index a0deb27..f6c8694 100644 --- a/src/settings/modals/BackupWarning.ts +++ b/src/settings/modals/BackupWarning.ts @@ -5,10 +5,16 @@ export default class BackupWarningModal extends Modal { plugin: FolderNotesPlugin; title: string; desc: string; - callback: (...args: any[]) => void; - args: any[]; - - constructor(plugin: FolderNotesPlugin, title: string, description: string, callback: (...args: any[]) => void, args: any[] = []) { + callback: (...args: unknown[]) => void; + args: unknown[]; + + constructor( + plugin: FolderNotesPlugin, + title: string, + description: string, + callback: (...args: unknown[]) => void, + args: unknown[] = [], + ) { super(plugin.app); this.plugin = plugin; this.title = title; @@ -17,7 +23,7 @@ export default class BackupWarningModal extends Modal { this.desc = description; } - onOpen() { + onOpen(): void { this.modalEl.addClass('fn-backup-warning-modal'); const { contentEl } = this; @@ -25,8 +31,7 @@ export default class BackupWarningModal extends Modal { contentEl.createEl('p', { text: this.desc }); - this.insertCustomHtml(); - + // eslint-disable-next-line max-len contentEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).style.color = '#fb464c'; const buttonContainer = contentEl.createDiv({ cls: 'fn-modal-button-container' }); @@ -45,11 +50,7 @@ export default class BackupWarningModal extends Modal { }); } - insertCustomHtml(): void { - - } - - onClose() { + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/settings/modals/CreateFnForEveryFolder.ts b/src/settings/modals/CreateFnForEveryFolder.ts index 0380886..048664e 100644 --- a/src/settings/modals/CreateFnForEveryFolder.ts +++ b/src/settings/modals/CreateFnForEveryFolder.ts @@ -1,5 +1,4 @@ -import type { App, ButtonComponent } from 'obsidian'; -import { Modal, Setting, TFolder, Notice } from 'obsidian'; +import { Modal, Setting, TFolder, Notice, type App, type ButtonComponent } from 'obsidian'; import type FolderNotesPlugin from '../../main'; import { createFolderNote, getFolderNote } from 'src/functions/folderNoteFunctions'; import { getTemplatePlugins } from 'src/template'; @@ -15,7 +14,8 @@ export default class ConfirmationModal extends Modal { this.app = app; this.extension = plugin.settings.folderNoteType; } - onOpen() { + + onOpen(): void { this.modalEl.addClass('fn-confirmation-modal'); let templateFolderPath: string; const { templateFolder, templaterPlugin } = getTemplatePlugins(this.plugin.app); @@ -23,19 +23,29 @@ export default class ConfirmationModal extends Modal { templateFolderPath = ''; } if (templaterPlugin) { - templateFolderPath = templaterPlugin.plugin?.settings?.templates_folder as string; - } else { + templateFolderPath = ( + templaterPlugin as unknown as { + plugin?: { settings?: { templates_folder?: string } } + } + ).plugin?.settings?.templates_folder as string; + } else if (templateFolder) { templateFolderPath = templateFolder; } const { contentEl } = this; contentEl.createEl('h2', { text: 'Create folder note for every folder' }); const setting = new Setting(contentEl); + // eslint-disable-next-line max-len setting.infoEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).style.color = '#fb464c'; + // eslint-disable-next-line max-len setting.infoEl.createEl('p', { text: 'This feature will create a folder note for every folder in your vault.' }); + // eslint-disable-next-line max-len setting.infoEl.createEl('p', { text: 'Every folder that already has a folder note will be ignored.' }); setting.infoEl.createEl('p', { text: 'Every excluded folder will be ignored.' }); - if (!this.plugin.settings.templatePath || this.plugin.settings.templatePath?.trim() === '') { + if ( + !this.plugin.settings.templatePath || + this.plugin.settings.templatePath?.trim() === '' + ) { new Setting(contentEl) .setName('Folder note file extension') .setDesc('Choose the file extension for the folder notes.') @@ -56,17 +66,24 @@ export default class ConfirmationModal extends Modal { cb.setCta(); cb.buttonEl.focus(); cb.onClick(async () => { - if (this.plugin.settings.templatePath && this.plugin.settings.templatePath.trim() !== '') { + if ( + this.plugin.settings.templatePath && + this.plugin.settings.templatePath.trim() !== '' + ) { this.extension = '.' + this.plugin.settings.templatePath.split('.').pop(); } if (this.extension === '.ask') { return new Notice('Please choose a file extension'); } this.close(); - const folders = this.app.vault.getAllLoadedFiles().filter((file) => file.parent instanceof TFolder); + const folders = this.app.vault + .getAllLoadedFiles() + .filter((file) => file.parent instanceof TFolder); for (const folder of folders) { if (folder instanceof TFolder) { - const excludedFolder = getExcludedFolder(this.plugin, folder.path, true); + const excludedFolder = getExcludedFolder( + this.plugin, folder.path, true, + ); if (excludedFolder) continue; if (folder.path === templateFolderPath) continue; const folderNote = getFolderNote(this.plugin, folder.path); @@ -83,7 +100,8 @@ export default class ConfirmationModal extends Modal { }); }); } - onClose() { + + onClose(): void { const { contentEl } = this; contentEl.empty(); } diff --git a/src/settings/modals/RenameFns.ts b/src/settings/modals/RenameFns.ts index 56cd925..b2183c6 100644 --- a/src/settings/modals/RenameFns.ts +++ b/src/settings/modals/RenameFns.ts @@ -3,7 +3,13 @@ import type FolderNotesPlugin from 'src/main'; import { Setting } from 'obsidian'; export default class RenameFolderNotesModal extends BackupWarningModal { - constructor(plugin: FolderNotesPlugin, title: string, description: string, callback: (...args: any[]) => void, args: any[] = []) { + constructor( + plugin: FolderNotesPlugin, + title: string, + description: string, + callback: (...args: unknown[]) => void, + args: unknown[] = [], + ) { super(plugin, title, description, callback, args); } @@ -11,6 +17,7 @@ export default class RenameFolderNotesModal extends BackupWarningModal { const { contentEl } = this; new Setting(contentEl) .setName('Old Folder Note Name') + // eslint-disable-next-line max-len .setDesc('Every folder note that matches this name will be renamed to the new folder note name.') .addText((text) => text .setPlaceholder('Enter the old folder note name') @@ -22,6 +29,7 @@ export default class RenameFolderNotesModal extends BackupWarningModal { new Setting(contentEl) .setName('New Folder Note Name') + // eslint-disable-next-line max-len .setDesc('Every folder note that matches the old folder note name will be renamed to this name.') .addText((text) => text .setPlaceholder('Enter the new folder note name') diff --git a/src/suggesters/FolderSuggester.ts b/src/suggesters/FolderSuggester.ts index e3d07b6..ce4d34e 100644 --- a/src/suggesters/FolderSuggester.ts +++ b/src/suggesters/FolderSuggester.ts @@ -1,7 +1,6 @@ // Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater -import type { TAbstractFile } from 'obsidian'; -import { TFolder } from 'obsidian'; +import { TFolder, type TAbstractFile } from 'obsidian'; import { TextInputSuggest } from './Suggest'; import type FolderNotesPlugin from '../main'; export enum FileSuggestMode { @@ -36,13 +35,18 @@ export class FolderSuggest extends TextInputSuggest { if (this.folder) { files = this.folder.children; } else { - files = this.plugin.app.vault.getAllLoadedFiles().slice(0,100); + const MAX_FILE_SUGGESTIONS = 100; + files = this.plugin.app.vault.getAllLoadedFiles().slice(0, MAX_FILE_SUGGESTIONS); } files.forEach((folder: TAbstractFile) => { if ( folder instanceof TFolder && - folder.path.toLowerCase().contains(lower_input_str) && - (!this.plugin.settings.excludeFolders.find((f) => f.path === folder.path) || this.whitelistSuggester) + folder.path.toLowerCase().contains(lower_input_str) && + ( + !this.plugin.settings.excludeFolders.find( + (f) => f.path === folder.path, + ) || this.whitelistSuggester + ) ) { folders.push(folder); } diff --git a/src/suggesters/Suggest.ts b/src/suggesters/Suggest.ts index 4a3fb02..9f2822b 100644 --- a/src/suggesters/Suggest.ts +++ b/src/suggesters/Suggest.ts @@ -1,10 +1,7 @@ // Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater - -import type { ISuggestOwner } from 'obsidian'; -import { Scope } from 'obsidian'; -import type { Instance as PopperInstance } from '@popperjs/core'; -import { createPopper } from '@popperjs/core'; +import { Scope, type ISuggestOwner } from 'obsidian'; +import { createPopper, type Instance as PopperInstance } from '@popperjs/core'; import type FolderNotesPlugin from 'src/main'; const wrapAround = (value: number, size: number): number => { @@ -73,7 +70,7 @@ class Suggest { this.setSelectedItem(item, false); } - setSuggestions(values: T[]) { + setSuggestions(values: T[]): void { this.containerEl.empty(); const suggestionEls: HTMLDivElement[] = []; @@ -88,14 +85,14 @@ class Suggest { this.setSelectedItem(0, false); } - useSelectedItem(event: MouseEvent | KeyboardEvent) { + useSelectedItem(event: MouseEvent | KeyboardEvent): void { const currentValue = this.values[this.selectedItem]; if (currentValue) { this.owner.selectSuggestion(currentValue, event); } } - setSelectedItem(selectedIndex: number, scrollIntoView: boolean) { + setSelectedItem(selectedIndex: number, scrollIntoView: boolean): void { const normalizedIndex = wrapAround( selectedIndex, this.suggestions.length, @@ -157,7 +154,7 @@ export abstract class TextInputSuggest implements ISuggestOwner { if (suggestions.length > 0) { this.suggest.setSuggestions(suggestions); - // @ts-ignore + // @ts-expect-error App may not exist this.open(app.dom.appContainerEl, this.inputEl); } else { this.close(); @@ -175,7 +172,7 @@ export abstract class TextInputSuggest implements ISuggestOwner { { name: 'sameWidth', enabled: true, - fn: ({ state, instance }) => { + fn: ({ state, instance }): void => { // Note: positioning needs to be calculated twice - // first pass - positioning it according to the width of the popper // second pass - position it with the width bound to the reference element diff --git a/src/suggesters/TemplateSuggester.ts b/src/suggesters/TemplateSuggester.ts index 0e26932..60b6f83 100644 --- a/src/suggesters/TemplateSuggester.ts +++ b/src/suggesters/TemplateSuggester.ts @@ -1,5 +1,4 @@ -import type { TAbstractFile } from 'obsidian'; -import { TFile, TFolder, Vault, AbstractInputSuggest } from 'obsidian'; +import { TFile, TFolder, Vault, AbstractInputSuggest, type TAbstractFile } from 'obsidian'; import type FolderNotesPlugin from '../main'; import { getTemplatePlugins } from 'src/template'; export enum FileSuggestMode { @@ -39,12 +38,21 @@ export class TemplateSuggest extends AbstractInputSuggest { let folder: TFolder | TAbstractFile | null = null; if (templaterPlugin) { folder = this.plugin.app.vault.getAbstractFileByPath( - templaterPlugin.plugin?.settings?.templates_folder as string, + (templaterPlugin as unknown as { + plugin?: { settings?: { templates_folder?: string } } + }).plugin?.settings?.templates_folder as string, ); if (!(folder instanceof TFolder)) { - return [{ path: '', name: 'You need to set the Templates folder in the Templater settings first.' } as TFile]; + return [ + { + path: '', + name: + // eslint-disable-next-line max-len + 'You need to set the Templates folder in the Templater settings first.', + } as TFile, + ]; } - } else { + } else if (templateFolder) { folder = this.plugin.app.vault.getAbstractFileByPath(templateFolder) as TFolder; } diff --git a/src/template.ts b/src/template.ts index 09753cb..48240fd 100644 --- a/src/template.ts +++ b/src/template.ts @@ -1,12 +1,41 @@ import { TFile, WorkspaceLeaf, type App } from 'obsidian'; import type FolderNotesPlugin from './main'; +interface TemplatesPlugin { + enabled: boolean; + instance: { + options: { + folder: string; + }; + insertTemplate: (templateFile: TFile) => Promise; + }; +} + +interface TemplaterPlugin { + settings?: { + empty_file_template?: string; + template_folder?: string; + }; + templater?: { + write_template_to_file: (templateFile: TFile, targetFile: TFile) => Promise; + }; +} + +interface TemplatePluginReturn { + templatesPlugin: TemplatesPlugin | null; + templatesEnabled: boolean; + templaterPlugin: TemplaterPlugin['templater'] | null; + templaterEnabled: boolean; + templaterEmptyFileTemplate?: string; + templateFolder?: string; +} + export async function applyTemplate( plugin: FolderNotesPlugin, file: TFile, leaf?: WorkspaceLeaf | null, templatePath?: string, -) { +): Promise { const fileContent = await plugin.app.vault.read(file).catch((err) => { console.error(`Error reading file ${file.path}:`, err); }); @@ -25,14 +54,15 @@ export async function applyTemplate( templaterPlugin, } = getTemplatePlugins(plugin.app); const templateContent = await plugin.app.vault.read(templateFile); + // eslint-disable-next-line max-len if (templateContent.includes('==âš  Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. âš ==')) { return; } // Prioritize Templater if both plugins are enabled - if (templaterEnabled) { + if (templaterEnabled && templaterPlugin) { return await templaterPlugin.write_template_to_file(templateFile, file); - } else if (templatesEnabled) { + } else if (templatesEnabled && templatesPlugin) { if (leaf instanceof WorkspaceLeaf) { await leaf.openFile(file); } @@ -47,23 +77,37 @@ export async function applyTemplate( } } -export function getTemplatePlugins(app: App) { - const templatesPlugin = (app as any).internalPlugins.plugins.templates; - const templatesEnabled = templatesPlugin.enabled; - const templaterPlugin = (app as any).plugins.plugins['templater-obsidian']; - const templaterEnabled = (app as any).plugins.enabledPlugins.has('templater-obsidian'); +export function getTemplatePlugins(app: App): TemplatePluginReturn { + const appAsUnknown = app as unknown as { + internalPlugins: { + plugins: { + templates: TemplatesPlugin; + }; + }; + plugins: { + plugins: { + 'templater-obsidian': TemplaterPlugin; + }; + enabledPlugins: Set; + }; + }; + + const templatesPlugin = appAsUnknown.internalPlugins.plugins.templates; + const templatesEnabled = templatesPlugin?.enabled ?? false; + const templaterPlugin = appAsUnknown.plugins.plugins['templater-obsidian']; + const templaterEnabled = appAsUnknown.plugins.enabledPlugins.has('templater-obsidian'); const templaterEmptyFileTemplate = templaterPlugin && templaterPlugin.settings?.empty_file_template; const templateFolder = templatesEnabled ? templatesPlugin.instance.options.folder - : templaterPlugin?.settings.template_folder; + : templaterPlugin?.settings?.template_folder; return { - templatesPlugin, + templatesPlugin: templatesPlugin || null, templatesEnabled, - templaterPlugin: templaterPlugin?.templater, + templaterPlugin: templaterPlugin?.templater || null, templaterEnabled, templaterEmptyFileTemplate, templateFolder, From e88ccfeb06a9e2a0a0c340e918287e47e90eaf10 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:46:07 +0200 Subject: [PATCH 26/47] Update obsidian-folder-overview --- src/obsidian-folder-overview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 5323f27..37008ed 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 5323f27922aff0165dca78770f24a7d8a99de7c0 +Subproject commit 37008ed555811b06e5e9c3547079368e0cce8113 From 3e23140bfb76c435b0d090ffb8486ef23239f4b0 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:36:40 +0200 Subject: [PATCH 27/47] Fix # 275 --- src/main.ts | 30 ++++++++++++++++++---------- src/obsidian-folder-overview | 2 +- src/settings/FileExplorerSettings.ts | 9 ++++++++- styles.css | 6 ++++-- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/main.ts b/src/main.ts index ee94694..ad5bf0b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -84,6 +84,9 @@ export default class FolderNotesPlugin extends Plugin { if (this.settings.hideCollapsingIcon) { document.body.classList.add('fn-hide-collapse-icon'); } + if (this.settings.ignoreAttachmentFolder) { + document.body.classList.add('fn-ignore-attachment-folder'); + } if (!this.settings.highlightFolder) { document.body.classList.add('disable-folder-highlight'); } @@ -433,7 +436,7 @@ export default class FolderNotesPlugin extends Plugin { updateViewDropdown: typeof updateViewDropdown = updateViewDropdown; isEmptyFolderNoteFolder(folder: TFolder): boolean { - const attachmentFolderPath = this.app.vault.getConfig('attachmentFolderPath') as string; + let attachmentFolderPath = this.app.vault.getConfig('attachmentFolderPath') as string; const cleanAttachmentFolderPath = attachmentFolderPath?.replace('./', '') || ''; const attachmentsAreInRootFolder = attachmentFolderPath === './' || attachmentFolderPath === ''; @@ -441,22 +444,27 @@ export default class FolderNotesPlugin extends Plugin { if (folder.children.length === 0) { addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this); } + attachmentFolderPath = `${folder.path}/${cleanAttachmentFolderPath}`; if (folder.children.length === threshold) { + addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this); return true; } else if (folder.children.length > threshold) { if (attachmentsAreInRootFolder) { return false; - } else if (this.settings.ignoreAttachmentFolder - && this.app.vault.getAbstractFileByPath( - `${folder.path}/${cleanAttachmentFolderPath}`)) { - const folderPath = `${folder.path}/${cleanAttachmentFolderPath}`; - const attachmentFolder = this.app.vault.getAbstractFileByPath(folderPath); - if (attachmentFolder instanceof TFolder - && folder.children.length <= threshold + 1) { - if (!folder.collapsed) { - getFileExplorerElement(folder.path, this)?.click(); - } + } else if ( + this.app.vault.getAbstractFileByPath(attachmentFolderPath) instanceof TFolder + ) { + const attachmentFolder = this.app.vault.getAbstractFileByPath(attachmentFolderPath); + if ( + attachmentFolder instanceof TFolder && + folder.children.length <= threshold + 1 + ) { + addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this); + addCSSClassToFileExplorerEl( + folder.path, 'fn-has-attachment-folder', + false, this, + ); } return folder.children.length <= threshold + 1; } diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 37008ed..69f6e80 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 37008ed555811b06e5e9c3547079368e0cce8113 +Subproject commit 69f6e80b248e6317ca3d9587f27891ce86f55c79 diff --git a/src/settings/FileExplorerSettings.ts b/src/settings/FileExplorerSettings.ts index c69e620..ee9297e 100644 --- a/src/settings/FileExplorerSettings.ts +++ b/src/settings/FileExplorerSettings.ts @@ -135,12 +135,14 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise { settingsTab.plugin.settings.hideCollapsingIcon = value; - await settingsTab.plugin.saveSettings(); if (value) { + console.log(document.body.classList.contains('fn-hide-collapse-icon')); document.body.classList.add('fn-hide-collapse-icon'); } else { + console.log(document.body.classList.contains('fn-hide-collapse-icon')); document.body.classList.remove('fn-hide-collapse-icon'); } + await settingsTab.plugin.saveSettings(); settingsTab.display(); }), ); @@ -170,6 +172,11 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise { + if (value) { + document.body.classList.add('fn-ignore-attachment-folder'); + } else { + document.body.classList.remove('fn-ignore-attachment-folder'); + } settingsTab.plugin.settings.ignoreAttachmentFolder = value; await settingsTab.plugin.saveSettings(); }), diff --git a/styles.css b/styles.css index 1bfa9ea..84eb68f 100644 --- a/styles.css +++ b/styles.css @@ -223,8 +223,10 @@ li:has(.fv-link-list-item), .fn-has-no-files .collapse-icon, .fn-hide-collapse-icon .has-folder-note.only-has-folder-note .tree-item-icon, -.fn-hide-empty-collapse-icon .fn-empty-folder .tree-item-icon, -.only-has-folder-note:not(.is-collapsed):not(.show-folder-note-in-explorer)>.nav-folder-children { +body.fn-ignore-attachment-folder.fn-hide-collapse-icon .only-has-folder-note .fn-empty-folder.fn-has-attachment-folder .tree-item-icon, +body.fn-hide-collapse-icon .only-has-folder-note .fn-empty-folder:not(.fn-has-attachment-folder) .tree-item-icon, +body.fn-hide-empty-collapse-icon :not(.only-has-folder-note) > .fn-empty-folder:not(.fn-has-attachment-folder) .tree-item-icon, +body.fn-hide-collapse-icon.only-has-folder-note:not(.is-collapsed):not(.show-folder-note-in-explorer)>.nav-folder-children { display: none; } From f670410cf26cc5707700790597d6cf2b7ab9c79e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 13 Aug 2025 13:37:12 +0000 Subject: [PATCH 28/47] Update manifest-beta.json to version 1.8.17-3-beta in main branch --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index c97ba08..56c64be 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes beta", - "version": "1.8.17-2-beta", + "version": "1.8.17-3-beta", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From b24b25ef342b272058aeb9e3d51434ceea6119df Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:40:30 +0200 Subject: [PATCH 29/47] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f459e2a..7bf0f65 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "author": "Lost Paul", "license": "GPL-3.0-or-later", "devDependencies": { - "@eslint/js": "^9.32.0", + "@eslint/js": "^8.57.1", "@types/node": "^16.11.6", "@typescript-eslint/eslint-plugin": "5.29.0", "@typescript-eslint/parser": "5.29.0", From 8e2c3376a67c5a09a4e3f26005ca5c4be8ec8d65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 13 Aug 2025 13:41:20 +0000 Subject: [PATCH 30/47] Update manifest-beta.json to version 1.8.17-4-beta in main branch --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index 56c64be..fc5c57a 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes beta", - "version": "1.8.17-3-beta", + "version": "1.8.17-4-beta", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From 765c048fbd9cdfcc2fcbf93f94d7be7c7eec5c67 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:14:58 +0200 Subject: [PATCH 31/47] Update packages --- package-lock.json | 1430 +++++++++------------------------------------ package.json | 4 +- 2 files changed, 280 insertions(+), 1154 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7886651..552d51a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,10 @@ "@popperjs/core": "^2.11.6" }, "devDependencies": { - "@eslint/js": "^9.32.0", + "@eslint/js": "^8.57.1", "@types/node": "^16.11.6", - "@typescript-eslint/eslint-plugin": "5.29.0", - "@typescript-eslint/parser": "5.29.0", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", "builtin-modules": "3.3.0", "esbuild": "0.14.47", "eslint": "^9.32.0", @@ -198,16 +198,13 @@ } }, "node_modules/@eslint/js": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", - "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@eslint/object-schema": { @@ -447,124 +444,69 @@ "@types/estree": "*" } }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", - "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/type-utils": "5.29.0", - "@typescript-eslint/utils": "5.29.0", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", + "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/type-utils": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" + "@typescript-eslint/parser": "^8.39.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", - "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", + "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { @@ -589,31 +531,18 @@ "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", - "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", - "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/@typescript-eslint/scope-manager": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", - "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0" + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -638,131 +567,174 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", - "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", + "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "5.29.0", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.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": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", + "debug": "^4.3.4" }, "engines": { - "node": ">=8.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", - "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", - "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", + "node_modules/@typescript-eslint/utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", - "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.29.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.39.1", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -831,15 +803,6 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -847,14 +810,6 @@ "dev": true, "license": "MIT" }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -1072,64 +1027,6 @@ "node": ">=10" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/electron": { "version": "31.4.0", "resolved": "https://registry.npmjs.org/electron/-/electron-31.4.0.tgz", @@ -1179,39 +1076,6 @@ "node": ">=6" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/esbuild": { "version": "0.14.47", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.47.tgz", @@ -1678,58 +1542,30 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "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": "MIT", - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, + "license": "Apache-2.0", "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "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==", - "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" } }, "node_modules/espree": { @@ -1750,19 +1586,6 @@ "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==", - "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/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -1984,44 +1807,6 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "optional": true, - "peer": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -2050,25 +1835,6 @@ "node": ">=10.13.0" } }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, "node_modules/globals": { "version": "16.3.0", "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", @@ -2082,58 +1848,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/got": { "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", @@ -2183,62 +1897,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", @@ -2375,14 +2033,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -2447,20 +2097,6 @@ "node": ">=8" } }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2541,17 +2177,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/obsidian": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.6.6.tgz", @@ -2677,15 +2302,6 @@ "node": ">=8" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -2780,18 +2396,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", @@ -2832,25 +2436,6 @@ "node": ">=0.10.0" } }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -2887,45 +2472,6 @@ "node": ">=10" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2949,23 +2495,6 @@ "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3043,27 +2572,6 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3308,19 +2816,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/typescript-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==", - "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/typescript-eslint/node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", @@ -3559,9 +3054,9 @@ } }, "@eslint/js": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", - "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true }, "@eslint/object-schema": { @@ -3740,75 +3235,41 @@ "@types/estree": "*" } }, - "@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@types/node": "*" - } - }, "@typescript-eslint/eslint-plugin": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", - "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", + "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/type-utils": "5.29.0", - "@typescript-eslint/utils": "5.29.0", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/type-utils": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" }, "dependencies": { - "@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true } } }, "@typescript-eslint/parser": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", - "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", + "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4" } }, @@ -3821,24 +3282,16 @@ "@typescript-eslint/tsconfig-utils": "^8.38.0", "@typescript-eslint/types": "^8.38.0", "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", - "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", - "dev": true - } } }, "@typescript-eslint/scope-manager": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", - "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0" + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" } }, "@typescript-eslint/tsconfig-utils": { @@ -3849,77 +3302,100 @@ "requires": {} }, "@typescript-eslint/type-utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", - "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", + "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.29.0", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^2.1.0" + } + }, + "@typescript-eslint/types": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", + "dev": true, + "requires": { + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.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" }, "dependencies": { - "@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "@typescript-eslint/project-service": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", + "debug": "^4.3.4" } }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "@typescript-eslint/tsconfig-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", + "dev": true, + "requires": {} + }, + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "balanced-match": "^1.0.0" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } } } }, - "@typescript-eslint/types": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", - "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", - "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", + "@typescript-eslint/utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" } }, "@typescript-eslint/visitor-keys": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", - "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", "dev": true, "requires": { - "@typescript-eslint/types": "5.29.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.39.1", + "eslint-visitor-keys": "^4.2.1" } }, "acorn": { @@ -3962,26 +3438,12 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, "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 }, - "boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "dev": true, - "optional": true, - "peer": true - }, "brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -4136,49 +3598,6 @@ "dev": true, "peer": true }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, - "define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true, - "peer": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, "electron": { "version": "31.4.0", "resolved": "https://registry.npmjs.org/electron/-/electron-31.4.0.tgz", @@ -4220,33 +3639,6 @@ "dev": true, "peer": true }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "optional": true, - "peer": true - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true, - "peer": true - }, "esbuild": { "version": "0.14.47", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.47.tgz", @@ -4464,10 +3856,10 @@ "optionator": "^0.9.3" }, "dependencies": { - "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==", + "@eslint/js": { + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", "dev": true } } @@ -4482,27 +3874,10 @@ "estraverse": "^5.2.0" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "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 }, "espree": { @@ -4514,14 +3889,6 @@ "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" - }, - "dependencies": { - "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 - } } }, "esquery": { @@ -4693,35 +4060,6 @@ "universalify": "^0.1.0" } }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "optional": true, - "peer": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -4741,65 +4079,12 @@ "is-glob": "^4.0.3" } }, - "global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - } - }, "globals": { "version": "16.3.0", "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true }, - "globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, "got": { "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", @@ -4839,44 +4124,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "optional": true, - "peer": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "optional": true, - "peer": true - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "function-bind": "^1.1.2" - } - }, "http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", @@ -4977,14 +4224,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "optional": true, - "peer": true - }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -5036,17 +4275,6 @@ "dev": true, "peer": true }, - "matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "escape-string-regexp": "^4.0.0" - } - }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -5104,14 +4332,6 @@ "dev": true, "peer": true }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "optional": true, - "peer": true - }, "obsidian": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.6.6.tgz", @@ -5199,12 +4419,6 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -5261,12 +4475,6 @@ "dev": true, "peer": true }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, "resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", @@ -5296,22 +4504,6 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - } - }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5327,35 +4519,6 @@ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "optional": true, - "peer": true - }, - "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "type-fest": "^0.13.1" - }, - "dependencies": { - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true, - "peer": true - } - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5371,20 +4534,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "optional": true, - "peer": true - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -5439,23 +4588,6 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5591,12 +4723,6 @@ "balanced-match": "^1.0.0" } }, - "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 - }, "ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", diff --git a/package.json b/package.json index 7bf0f65..22564a3 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "devDependencies": { "@eslint/js": "^8.57.1", "@types/node": "^16.11.6", - "@typescript-eslint/eslint-plugin": "5.29.0", - "@typescript-eslint/parser": "5.29.0", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", "builtin-modules": "3.3.0", "esbuild": "0.14.47", "eslint": "^9.32.0", From e826fe674077acaa4bdf4a73b8ddf3246f5d1a2e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 14 Aug 2025 08:15:24 +0000 Subject: [PATCH 32/47] Update manifest-beta.json to version 1.8.17-5-beta in main branch --- manifest-beta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest-beta.json b/manifest-beta.json index fc5c57a..c97263b 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes beta", - "version": "1.8.17-4-beta", + "version": "1.8.17-5-beta", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From 03b6de9db74137463fef71aadbdd1dc31767b965 Mon Sep 17 00:00:00 2001 From: Nightwish2710 Date: Mon, 18 Aug 2025 14:21:10 +0700 Subject: [PATCH 33/47] feat: update command menu for mobile rendering --- src/Commands.ts | 330 ++++++++++++++++++++++++------------------------ 1 file changed, 168 insertions(+), 162 deletions(-) diff --git a/src/Commands.ts b/src/Commands.ts index a27b541..1c0843f 100644 --- a/src/Commands.ts +++ b/src/Commands.ts @@ -298,208 +298,214 @@ export class Commands { } } - // eslint-disable-next-line complexity - menu.addItem(async (menuItem) => { - if ( - Platform.isDesktop && - !Platform.isTablet && - this.plugin.settings.useSubmenus - ) { - menuItem - .setTitle('Folder Note Commands') - .setIcon('folder-edit'); - } - let subMenu: Menu; - if ( - !Platform.isDesktopApp || - !Platform.isDesktop || - Platform.isTablet || - !this.plugin.settings.useSubmenus - ) { - subMenu = menu; - menuItem.setDisabled(true); - } else { - subMenu = menuItem.setSubmenu() as Menu; - } - if (file instanceof TFile) { - subMenu.addItem((subItem) => { - subItem.setTitle('Create folder note') - .setIcon('edit') - .onClick(async () => { - if (!folder) return; - let newPath = folder.path + '/' + file.basename; - if (folder.path === '' || folder.path === '/') { - newPath = file.basename; - } - if (this.plugin.app.vault.getAbstractFileByPath(newPath)) { - return new Notice('Folder already exists'); - } - const automaticallyCreateFolderNote = - this.plugin.settings.autoCreate; - this.plugin.settings.autoCreate = false; - this.plugin.saveSettings(); - await this.plugin.app.vault.createFolder(newPath); - const newFolder = this.plugin.app.vault - .getAbstractFileByPath(newPath); - if (!(newFolder instanceof TFolder)) return; - await createFolderNote( - this.plugin, - newFolder.path, - true, - '.' + file.extension, - false, - file, - ); - this.plugin.settings.autoCreate = automaticallyCreateFolderNote; - this.plugin.saveSettings(); - }); + const addFolderNoteActions = (menu: Menu) => { + if (file instanceof TFile) { + menu.addItem((item) => { + item.setTitle('Create folder note'); + item.setIcon('edit'); + item.onClick(async () => { + if (!folder) return; + let newPath = folder.path + '/' + file.basename; + if (folder.path === '' || folder.path === '/') { + newPath = file.basename; + } + if (this.plugin.app.vault.getAbstractFileByPath(newPath)) { + return new Notice('Folder already exists'); + } + const automaticallyCreateFolderNote = + this.plugin.settings.autoCreate; + this.plugin.settings.autoCreate = false; + this.plugin.saveSettings(); + await this.plugin.app.vault.createFolder(newPath); + const newFolder = this.plugin.app.vault + .getAbstractFileByPath(newPath); + if (!(newFolder instanceof TFolder)) return; + await createFolderNote( + this.plugin, + newFolder.path, + true, + '.' + file.extension, + false, + file, + ); + this.plugin.settings.autoCreate = automaticallyCreateFolderNote; + this.plugin.saveSettings(); + }); }); + if (getFolderPathFromString(file.path) === '') return; - if (!(folder instanceof TFolder)) return; - if (folder.path === '' || folder.path === '/') return; - subMenu.addItem((item) => { - item.setTitle(`Turn into folder note for ${folder?.name}`) - .setIcon('edit') - .onClick(() => { - if (!folder || !(folder instanceof TFolder)) return; - const folderNote = getFolderNote(this.plugin, folder.path); - turnIntoFolderNote(this.plugin, file, folder, folderNote); - }); + + if (!(folder instanceof TFolder)) return; + + if (folder.path === '' || folder.path === '/') return; + + menu.addItem((item) => { + item.setTitle(`Turn into folder note for ${folder?.name}`); + item.setIcon('edit'); + item.onClick(() => { + if (!folder || !(folder instanceof TFolder)) return; + const folderNote = getFolderNote(this.plugin, folder.path); + turnIntoFolderNote(this.plugin, file, folder, folderNote); + }); }); } + if (!(file instanceof TFolder)) return; + const excludedFolder = getExcludedFolder(this.plugin, file.path, false); const detachedExcludedFolder = getDetachedFolder(this.plugin, file.path); - if (excludedFolder && !excludedFolder.hideInSettings) { + + if (excludedFolder && !excludedFolder.hideInSettings) { // I'm not sure if I'm ever going to add this because of the possibility that a folder got more than one excluded - // subMenu.addItem((item) => { - // item.setTitle('Manage excluded folder') - // .setIcon('settings-2') - // .onClick(() => { - // if (excludedFolder instanceof ExcludedFolder) { - // new ExcludedFolderSettings(this.plugin.app, this.plugin, excludedFolder).open(); - // } else if (excludedFolder instanceof ExcludePattern) { - // new PatternSettings(this.plugin.app, this.plugin, excludedFolder).open(); - // } - // }) - // }) - subMenu.addItem((item) => { - item.setTitle('Remove folder from excluded folders') - .setIcon('trash') - .onClick(() => { - this.plugin.settings.excludeFolders = - this.plugin.settings.excludeFolders.filter( - (excluded) => - (excluded.path !== file.path) || excluded.detached, - ); - this.plugin.saveSettings(true); - new Notice('Successfully removed folder from excluded folders'); - }); + // menu.addItem((item) => { + // item.setTitle('Manage excluded folder'); + // item.setIcon('settings-2'); + // item.onClick(() => { + // if (excludedFolder instanceof ExcludedFolder) { + // new ExcludedFolderSettings(this.plugin.app, this.plugin, excludedFolder).open(); + // } else if (excludedFolder instanceof ExcludePattern) { + // new PatternSettings(this.plugin.app, this.plugin, excludedFolder).open(); + // } + // }); + // }); + + menu.addItem((item) => { + item.setTitle('Remove folder from excluded folders'); + item.setIcon('trash'); + item.onClick(() => { + this.plugin.settings.excludeFolders = + this.plugin.settings.excludeFolders.filter( + (excluded) => + (excluded.path !== file.path) || excluded.detached, + ); + this.plugin.saveSettings(true); + new Notice('Successfully removed folder from excluded folders'); + }); }); + return; } + if (detachedExcludedFolder) { - subMenu.addItem((item) => { - item.setTitle('Remove folder from detached folders') - .setIcon('trash') - .onClick(() => { - deleteExcludedFolder(this.plugin, detachedExcludedFolder); - }); + menu.addItem((item) => { + item.setTitle('Remove folder from detached folders'); + item.setIcon('trash'); + item.onClick(() => { + deleteExcludedFolder(this.plugin, detachedExcludedFolder); + }); }); } + if (detachedExcludedFolder) { return; } - subMenu.addItem((item) => { - item.setTitle('Exclude folder from folder notes') - .setIcon('x-circle') - .onClick(() => { - const newExcludedFolder = new ExcludedFolder( - file.path, - this.plugin.settings.excludeFolders.length, - undefined, - this.plugin, - ); - this.plugin.settings.excludeFolders.push(newExcludedFolder); - this.plugin.saveSettings(true); - new Notice('Successfully excluded folder from folder notes'); - }); + + menu.addItem((item) => { + item.setTitle('Exclude folder from folder notes'); + item.setIcon('x-circle'); + item.onClick(() => { + const newExcludedFolder = new ExcludedFolder( + file.path, + this.plugin.settings.excludeFolders.length, + undefined, + this.plugin, + ); + this.plugin.settings.excludeFolders.push(newExcludedFolder); + this.plugin.saveSettings(true); + new Notice('Successfully excluded folder from folder notes'); + }); }); + if (!(file instanceof TFolder)) return; - const folderNote = getFolderNote(this.plugin, file.path); - if (folderNote instanceof TFile && !detachedExcludedFolder) { - subMenu.addItem((item) => { - item.setTitle('Delete folder note') - .setIcon('trash') - .onClick(() => { - deleteFolderNote(this.plugin, folderNote, true); - }); + + const folderNote = getFolderNote(this.plugin, file.path); + + if (folderNote instanceof TFile && !detachedExcludedFolder) { + menu.addItem((item) => { + item.setTitle('Delete folder note'); + item.setIcon('trash'); + item.onClick(() => { + deleteFolderNote(this.plugin, folderNote, true); + }); }); - subMenu.addItem((item) => { - item.setTitle('Open folder note') - .setIcon('chevron-right-square') - .onClick(() => { - openFolderNote(this.plugin, folderNote); - }); + menu.addItem((item) => { + item.setTitle('Open folder note'); + item.setIcon('chevron-right-square'); + item.onClick(() => { + openFolderNote(this.plugin, folderNote); + }); }); - subMenu.addItem((item) => { - item.setTitle('Detach folder note') - .setIcon('unlink') - .onClick(() => { - detachFolderNote(this.plugin, folderNote); - }); + menu.addItem((item) => { + item.setTitle('Detach folder note'); + item.setIcon('unlink'); + item.onClick(() => { + detachFolderNote(this.plugin, folderNote); + }); }); - subMenu.addItem((item) => { - item.setTitle('Copy Obsidian URL') - .setIcon('link') - .onClick(() => { - this.app.copyObsidianUrl(folderNote); - }); + menu.addItem((item) => { + item.setTitle('Copy Obsidian URL'); + item.setIcon('link'); + item.onClick(() => { + this.app.copyObsidianUrl(folderNote); + }); }); if (this.plugin.settings.hideFolderNote) { if (excludedFolder?.showFolderNote) { - subMenu.addItem((item) => { - item.setTitle('Hide folder note in explorer') - .setIcon('eye-off') - .onClick(() => { - hideFolderNoteInFileExplorer(file.path, this.plugin); - }); + menu.addItem((item) => { + item.setTitle('Hide folder note in explorer'); + item.setIcon('eye-off'); + item.onClick(() => { + hideFolderNoteInFileExplorer(file.path, this.plugin); + }); }); } else { - subMenu.addItem((item) => { - item.setTitle('Show folder note in explorer') - .setIcon('eye') - .onClick(() => { - showFolderNoteInFileExplorer(file.path, this.plugin); - }); + menu.addItem((item) => { + item.setTitle('Show folder note in explorer'); + item.setIcon('eye'); + item.onClick(() => { + showFolderNoteInFileExplorer(file.path, this.plugin); + }); }); } } - } else { - subMenu.addItem((item) => { - item.setTitle('Create markdown folder note') - .setIcon('edit') - .onClick(() => { - createFolderNote(this.plugin, file.path, true, '.md'); - }); + menu.addItem((item) => { + item.setTitle('Create markdown folder note'); + item.setIcon('edit'); + item.onClick(() => { + createFolderNote(this.plugin, file.path, true, '.md'); + }); }); this.plugin.settings.supportedFileTypes.forEach((fileType) => { if (fileType === 'md') return; - subMenu.addItem((item) => { - item.setTitle(`Create ${fileType} folder note`) - .setIcon('edit') - .onClick(() => { - // eslint-disable-next-line max-len - createFolderNote(this.plugin, file.path, true, '.' + fileType); - }); + menu.addItem((item) => { + item.setTitle(`Create ${fileType} folder note`); + item.setIcon('edit'); + item.onClick(() => { + // eslint-disable-next-line max-len + createFolderNote(this.plugin, file.path, true, '.' + fileType); + }); }); }); } - }); + }; + + if ( + Platform.isDesktop && + !Platform.isTablet && + this.plugin.settings.useSubmenus + ) { + menu.addItem(async (item) => { + item.setTitle('Folder Note Commands').setIcon('folder-edit'); + let subMenu: Menu = item.setSubmenu() as Menu; + addFolderNoteActions(subMenu); + }) + } else { + addFolderNoteActions(menu); + } })); } From 203d9f4119df3b66790004f89d025d90f2501cbc Mon Sep 17 00:00:00 2001 From: Nightwish2710 Date: Mon, 18 Aug 2025 14:28:23 +0700 Subject: [PATCH 34/47] feat: update command menu for mobile rendering --- src/Commands.ts | 188 ++++++++++++++++++++++++------------------------ 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/src/Commands.ts b/src/Commands.ts index 1c0843f..b8f2a97 100644 --- a/src/Commands.ts +++ b/src/Commands.ts @@ -298,55 +298,55 @@ export class Commands { } } - const addFolderNoteActions = (menu: Menu) => { - if (file instanceof TFile) { + const addFolderNoteActions = (menu: Menu) => { + if (file instanceof TFile) { menu.addItem((item) => { item.setTitle('Create folder note'); item.setIcon('edit'); item.onClick(async () => { - if (!folder) return; - let newPath = folder.path + '/' + file.basename; - if (folder.path === '' || folder.path === '/') { - newPath = file.basename; - } - if (this.plugin.app.vault.getAbstractFileByPath(newPath)) { - return new Notice('Folder already exists'); - } - const automaticallyCreateFolderNote = - this.plugin.settings.autoCreate; - this.plugin.settings.autoCreate = false; - this.plugin.saveSettings(); - await this.plugin.app.vault.createFolder(newPath); - const newFolder = this.plugin.app.vault - .getAbstractFileByPath(newPath); - if (!(newFolder instanceof TFolder)) return; - await createFolderNote( - this.plugin, - newFolder.path, - true, - '.' + file.extension, - false, - file, - ); - this.plugin.settings.autoCreate = automaticallyCreateFolderNote; - this.plugin.saveSettings(); - }); + if (!folder) return; + let newPath = folder.path + '/' + file.basename; + if (folder.path === '' || folder.path === '/') { + newPath = file.basename; + } + if (this.plugin.app.vault.getAbstractFileByPath(newPath)) { + return new Notice('Folder already exists'); + } + const automaticallyCreateFolderNote = + this.plugin.settings.autoCreate; + this.plugin.settings.autoCreate = false; + this.plugin.saveSettings(); + await this.plugin.app.vault.createFolder(newPath); + const newFolder = this.plugin.app.vault + .getAbstractFileByPath(newPath); + if (!(newFolder instanceof TFolder)) return; + await createFolderNote( + this.plugin, + newFolder.path, + true, + '.' + file.extension, + false, + file, + ); + this.plugin.settings.autoCreate = automaticallyCreateFolderNote; + this.plugin.saveSettings(); + }); }); if (getFolderPathFromString(file.path) === '') return; - if (!(folder instanceof TFolder)) return; + if (!(folder instanceof TFolder)) return; - if (folder.path === '' || folder.path === '/') return; + if (folder.path === '' || folder.path === '/') return; - menu.addItem((item) => { + menu.addItem((item) => { item.setTitle(`Turn into folder note for ${folder?.name}`); item.setIcon('edit'); item.onClick(() => { - if (!folder || !(folder instanceof TFolder)) return; - const folderNote = getFolderNote(this.plugin, folder.path); - turnIntoFolderNote(this.plugin, file, folder, folderNote); - }); + if (!folder || !(folder instanceof TFolder)) return; + const folderNote = getFolderNote(this.plugin, folder.path); + turnIntoFolderNote(this.plugin, file, folder, folderNote); + }); }); } @@ -355,32 +355,32 @@ export class Commands { const excludedFolder = getExcludedFolder(this.plugin, file.path, false); const detachedExcludedFolder = getDetachedFolder(this.plugin, file.path); - if (excludedFolder && !excludedFolder.hideInSettings) { + if (excludedFolder && !excludedFolder.hideInSettings) { // I'm not sure if I'm ever going to add this because of the possibility that a folder got more than one excluded // menu.addItem((item) => { // item.setTitle('Manage excluded folder'); // item.setIcon('settings-2'); // item.onClick(() => { - // if (excludedFolder instanceof ExcludedFolder) { - // new ExcludedFolderSettings(this.plugin.app, this.plugin, excludedFolder).open(); - // } else if (excludedFolder instanceof ExcludePattern) { - // new PatternSettings(this.plugin.app, this.plugin, excludedFolder).open(); - // } - // }); + // if (excludedFolder instanceof ExcludedFolder) { + // new ExcludedFolderSettings(this.plugin.app, this.plugin, excludedFolder).open(); + // } else if (excludedFolder instanceof ExcludePattern) { + // new PatternSettings(this.plugin.app, this.plugin, excludedFolder).open(); + // } + // }); // }); menu.addItem((item) => { item.setTitle('Remove folder from excluded folders'); item.setIcon('trash'); item.onClick(() => { - this.plugin.settings.excludeFolders = - this.plugin.settings.excludeFolders.filter( - (excluded) => - (excluded.path !== file.path) || excluded.detached, - ); - this.plugin.saveSettings(true); - new Notice('Successfully removed folder from excluded folders'); - }); + this.plugin.settings.excludeFolders = + this.plugin.settings.excludeFolders.filter( + (excluded) => + (excluded.path !== file.path) || excluded.detached, + ); + this.plugin.saveSettings(true); + new Notice('Successfully removed folder from excluded folders'); + }); }); return; @@ -391,64 +391,64 @@ export class Commands { item.setTitle('Remove folder from detached folders'); item.setIcon('trash'); item.onClick(() => { - deleteExcludedFolder(this.plugin, detachedExcludedFolder); - }); + deleteExcludedFolder(this.plugin, detachedExcludedFolder); + }); }); } if (detachedExcludedFolder) { return; } - menu.addItem((item) => { + menu.addItem((item) => { item.setTitle('Exclude folder from folder notes'); item.setIcon('x-circle'); item.onClick(() => { - const newExcludedFolder = new ExcludedFolder( - file.path, - this.plugin.settings.excludeFolders.length, - undefined, - this.plugin, - ); - this.plugin.settings.excludeFolders.push(newExcludedFolder); - this.plugin.saveSettings(true); - new Notice('Successfully excluded folder from folder notes'); - }); + const newExcludedFolder = new ExcludedFolder( + file.path, + this.plugin.settings.excludeFolders.length, + undefined, + this.plugin, + ); + this.plugin.settings.excludeFolders.push(newExcludedFolder); + this.plugin.saveSettings(true); + new Notice('Successfully excluded folder from folder notes'); + }); }); if (!(file instanceof TFolder)) return; - const folderNote = getFolderNote(this.plugin, file.path); + const folderNote = getFolderNote(this.plugin, file.path); - if (folderNote instanceof TFile && !detachedExcludedFolder) { + if (folderNote instanceof TFile && !detachedExcludedFolder) { menu.addItem((item) => { item.setTitle('Delete folder note'); item.setIcon('trash'); item.onClick(() => { - deleteFolderNote(this.plugin, folderNote, true); - }); + deleteFolderNote(this.plugin, folderNote, true); + }); }); menu.addItem((item) => { item.setTitle('Open folder note'); item.setIcon('chevron-right-square'); item.onClick(() => { - openFolderNote(this.plugin, folderNote); - }); + openFolderNote(this.plugin, folderNote); + }); }); menu.addItem((item) => { item.setTitle('Detach folder note'); item.setIcon('unlink'); item.onClick(() => { - detachFolderNote(this.plugin, folderNote); - }); + detachFolderNote(this.plugin, folderNote); + }); }); menu.addItem((item) => { item.setTitle('Copy Obsidian URL'); item.setIcon('link'); item.onClick(() => { - this.app.copyObsidianUrl(folderNote); - }); + this.app.copyObsidianUrl(folderNote); + }); }); if (this.plugin.settings.hideFolderNote) { @@ -457,16 +457,16 @@ export class Commands { item.setTitle('Hide folder note in explorer'); item.setIcon('eye-off'); item.onClick(() => { - hideFolderNoteInFileExplorer(file.path, this.plugin); - }); + hideFolderNoteInFileExplorer(file.path, this.plugin); + }); }); } else { menu.addItem((item) => { item.setTitle('Show folder note in explorer'); item.setIcon('eye'); item.onClick(() => { - showFolderNoteInFileExplorer(file.path, this.plugin); - }); + showFolderNoteInFileExplorer(file.path, this.plugin); + }); }); } } @@ -475,8 +475,8 @@ export class Commands { item.setTitle('Create markdown folder note'); item.setIcon('edit'); item.onClick(() => { - createFolderNote(this.plugin, file.path, true, '.md'); - }); + createFolderNote(this.plugin, file.path, true, '.md'); + }); }); this.plugin.settings.supportedFileTypes.forEach((fileType) => { @@ -485,27 +485,27 @@ export class Commands { item.setTitle(`Create ${fileType} folder note`); item.setIcon('edit'); item.onClick(() => { - // eslint-disable-next-line max-len - createFolderNote(this.plugin, file.path, true, '.' + fileType); - }); + // eslint-disable-next-line max-len + createFolderNote(this.plugin, file.path, true, '.' + fileType); + }); }); }); } - }; + }; - if ( + if ( Platform.isDesktop && !Platform.isTablet && this.plugin.settings.useSubmenus - ) { - menu.addItem(async (item) => { - item.setTitle('Folder Note Commands').setIcon('folder-edit'); - let subMenu: Menu = item.setSubmenu() as Menu; - addFolderNoteActions(subMenu); - }) - } else { - addFolderNoteActions(menu); - } + ) { + menu.addItem(async (item) => { + item.setTitle('Folder Note Commands').setIcon('folder-edit'); + let subMenu: Menu = item.setSubmenu() as Menu; + addFolderNoteActions(subMenu); + }) + } else { + addFolderNoteActions(menu); + } })); } From 08b8056df64dcd9672a462ccbc136b3fc75e19b9 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Mon, 18 Aug 2025 09:53:19 +0200 Subject: [PATCH 35/47] Fix linter issues --- src/Commands.ts | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Commands.ts b/src/Commands.ts index b8f2a97..c64830d 100644 --- a/src/Commands.ts +++ b/src/Commands.ts @@ -270,6 +270,7 @@ export class Commands { fileCommands(): void { this.plugin.registerEvent( + // eslint-disable-next-line complexity this.app.workspace.on('file-menu', (menu: Menu, file: TAbstractFile) => { let folder: TAbstractFile | TFolder | null = file.parent; if (file instanceof TFile) { @@ -298,9 +299,10 @@ export class Commands { } } - const addFolderNoteActions = (menu: Menu) => { + // eslint-disable-next-line complexity + const addFolderNoteActions = (folderMenu: Menu): void => { if (file instanceof TFile) { - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Create folder note'); item.setIcon('edit'); item.onClick(async () => { @@ -339,7 +341,7 @@ export class Commands { if (folder.path === '' || folder.path === '/') return; - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle(`Turn into folder note for ${folder?.name}`); item.setIcon('edit'); item.onClick(() => { @@ -369,7 +371,7 @@ export class Commands { // }); // }); - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Remove folder from excluded folders'); item.setIcon('trash'); item.onClick(() => { @@ -387,7 +389,7 @@ export class Commands { } if (detachedExcludedFolder) { - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Remove folder from detached folders'); item.setIcon('trash'); item.onClick(() => { @@ -398,7 +400,7 @@ export class Commands { if (detachedExcludedFolder) { return; } - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Exclude folder from folder notes'); item.setIcon('x-circle'); item.onClick(() => { @@ -419,7 +421,7 @@ export class Commands { const folderNote = getFolderNote(this.plugin, file.path); if (folderNote instanceof TFile && !detachedExcludedFolder) { - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Delete folder note'); item.setIcon('trash'); item.onClick(() => { @@ -427,7 +429,7 @@ export class Commands { }); }); - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Open folder note'); item.setIcon('chevron-right-square'); item.onClick(() => { @@ -435,7 +437,7 @@ export class Commands { }); }); - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Detach folder note'); item.setIcon('unlink'); item.onClick(() => { @@ -443,7 +445,7 @@ export class Commands { }); }); - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Copy Obsidian URL'); item.setIcon('link'); item.onClick(() => { @@ -453,7 +455,7 @@ export class Commands { if (this.plugin.settings.hideFolderNote) { if (excludedFolder?.showFolderNote) { - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Hide folder note in explorer'); item.setIcon('eye-off'); item.onClick(() => { @@ -461,7 +463,7 @@ export class Commands { }); }); } else { - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Show folder note in explorer'); item.setIcon('eye'); item.onClick(() => { @@ -471,7 +473,7 @@ export class Commands { } } } else { - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle('Create markdown folder note'); item.setIcon('edit'); item.onClick(() => { @@ -481,11 +483,10 @@ export class Commands { this.plugin.settings.supportedFileTypes.forEach((fileType) => { if (fileType === 'md') return; - menu.addItem((item) => { + folderMenu.addItem((item) => { item.setTitle(`Create ${fileType} folder note`); item.setIcon('edit'); item.onClick(() => { - // eslint-disable-next-line max-len createFolderNote(this.plugin, file.path, true, '.' + fileType); }); }); @@ -494,15 +495,15 @@ export class Commands { }; if ( - Platform.isDesktop && - !Platform.isTablet && - this.plugin.settings.useSubmenus + Platform.isDesktop && + !Platform.isTablet && + this.plugin.settings.useSubmenus ) { menu.addItem(async (item) => { item.setTitle('Folder Note Commands').setIcon('folder-edit'); let subMenu: Menu = item.setSubmenu() as Menu; addFolderNoteActions(subMenu); - }) + }); } else { addFolderNoteActions(menu); } From 997ffb583bcdaad8ca67944e35b8e44b28addc44 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 Aug 2025 09:13:43 +0000 Subject: [PATCH 36/47] Update manifest.json to version --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 83a74ca..ad3738c 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes", - "version": "1.8.16", + "version": "1.8.17", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", From abfab4fc865f6c6509ab17751b142bbb5a138f8c Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Mon, 18 Aug 2025 11:35:20 +0200 Subject: [PATCH 37/47] Remove console.log --- src/settings/FileExplorerSettings.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/settings/FileExplorerSettings.ts b/src/settings/FileExplorerSettings.ts index ee9297e..906dcfa 100644 --- a/src/settings/FileExplorerSettings.ts +++ b/src/settings/FileExplorerSettings.ts @@ -136,10 +136,8 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise { settingsTab.plugin.settings.hideCollapsingIcon = value; if (value) { - console.log(document.body.classList.contains('fn-hide-collapse-icon')); document.body.classList.add('fn-hide-collapse-icon'); } else { - console.log(document.body.classList.contains('fn-hide-collapse-icon')); document.body.classList.remove('fn-hide-collapse-icon'); } await settingsTab.plugin.saveSettings(); From e0613b7d27d3ad192b1b2ea83a701af5a3bea23f Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Wed, 20 Aug 2025 09:53:59 +0200 Subject: [PATCH 38/47] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8c49d3a..118a9a0 100644 --- a/README.md +++ b/README.md @@ -13,5 +13,7 @@ The plugin can be downloaded by clicking on https://obsidian.md/plugins?id=folde The easiest option is to install the [BRAT plugin](https://obsidian.md/plugins?id=obsidian42-brat) and then to follow the following guide: https://tfthacker.com/brat-quick-guide & use this link https://github.com/LostPaul/obsidian-folder-notes to install the beta version. +Join the Discord server to chat about the beta and to also get the beta user role. + ## Discord server [For regular updates on Folder Notes and my other plugins, join the Discord server to get notified and participate in discussions.](https://discord.gg/4UQEDfQmuH) From fdade5d96b53084d772bfa1185729c8319c778b0 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 29 Nov 2025 20:28:04 +0100 Subject: [PATCH 39/47] Add option to use markdown links in folder overview --- src/obsidian-folder-overview | 2 +- src/settings/SettingsTab.ts | 1 + src/suggesters/FileSuggester.ts | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index 69f6e80..decf998 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit 69f6e80b248e6317ca3d9587f27891ce86f55c79 +Subproject commit decf99839f5cd7fee5402066edd12043b3ffed1e diff --git a/src/settings/SettingsTab.ts b/src/settings/SettingsTab.ts index 2eeb650..3139136 100644 --- a/src/settings/SettingsTab.ts +++ b/src/settings/SettingsTab.ts @@ -137,6 +137,7 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = { fmtpIntegration: false, titleSize: 1, isInCallout: false, + useWikilinks: true, }, useSubmenus: true, syncMove: true, diff --git a/src/suggesters/FileSuggester.ts b/src/suggesters/FileSuggester.ts index 3828036..879034d 100644 --- a/src/suggesters/FileSuggester.ts +++ b/src/suggesters/FileSuggester.ts @@ -14,7 +14,6 @@ export class FileSuggest extends TextInputSuggest { super(inputEl, plugin); } - get_error_msg(mode: FileSuggestMode): string { switch (mode) { case FileSuggestMode.TemplateFiles: From 1d7a065b8a9303261ff5e059886feecdf964ba93 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 29 Nov 2025 21:00:38 +0100 Subject: [PATCH 40/47] Update obsidian-folder-overview --- src/obsidian-folder-overview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obsidian-folder-overview b/src/obsidian-folder-overview index decf998..c5986ef 160000 --- a/src/obsidian-folder-overview +++ b/src/obsidian-folder-overview @@ -1 +1 @@ -Subproject commit decf99839f5cd7fee5402066edd12043b3ffed1e +Subproject commit c5986efabab87155c1ab652920deebbc75b883af From f4dbd3e93ca2e87532d0e4f449f31913fdda7f0b Mon Sep 17 00:00:00 2001 From: Sergey Kolesnik <1984175+stdword@users.noreply.github.com> Date: Thu, 18 Dec 2025 20:58:14 +0300 Subject: [PATCH 41/47] fix: make.md plugin integration --- src/functions/utils.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/functions/utils.ts b/src/functions/utils.ts index ec9f2ff..cca1363 100644 --- a/src/functions/utils.ts +++ b/src/functions/utils.ts @@ -44,7 +44,17 @@ export function getFileExplorer( plugin: FolderNotesPlugin | FolderOverviewPlugin, ): FileExplorerWorkspaceLeaf { // eslint-disable-next-line max-len - const leaf = plugin.app.workspace.getLeavesOfType('file-explorer')[0] as unknown as FileExplorerWorkspaceLeaf; + let leaf = plugin.app.workspace.getLeavesOfType('file-explorer')[0] as unknown as FileExplorerWorkspaceLeaf; + + /* make.md plugin integration */ + if (leaf.containerEl.lastChild.dataset.type == 'mk-path-view') { + plugin.app.workspace.iterateAllLeaves((x) => { + if (x.tabHeaderEl.dataset.type == 'file-explorer') { + leaf = x; + } + }); + } + return leaf; } From ef59e9998e2c29d3cddb859dfb4421f834b52333 Mon Sep 17 00:00:00 2001 From: Sergey Kolesnik <1984175+stdword@users.noreply.github.com> Date: Thu, 18 Dec 2025 21:00:54 +0300 Subject: [PATCH 42/47] fix: make.md plugin integration --- styles.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/styles.css b/styles.css index 84eb68f..a8a114b 100644 --- a/styles.css +++ b/styles.css @@ -8,6 +8,12 @@ display: none; } +/* make.md plugin integration */ +.hide-folder-note .mk-tree-node > .mk-tree-wrapper > .dropzone > .mk-tree-item.is-folder-note { + opacity: 40%; + display: flex; +} + .pointer-cursor, .has-folder-note .nav-folder-title-content:hover, .has-folder-note.view-header-breadcrumb:hover, @@ -337,4 +343,4 @@ body.fn-hide-collapse-icon.only-has-folder-note:not(.is-collapsed):not(.show-fol .is-phone .fn-overview-folder-path .setting-item-control { display: block; } -} \ No newline at end of file +} From 4d30ea696e4affe6efce7040698bbaea2223243f Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Fri, 2 Jan 2026 12:55:40 +0100 Subject: [PATCH 43/47] Fix #300 --- src/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index ad5bf0b..493726c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -30,7 +30,6 @@ import { refreshAllFolderStyles, setActiveFolder, removeActiveFolder, } from './functions/styleFunctions'; import { getExcludedFolder } from './ExcludeFolders/functions/folderFunctions'; -import type { FileExplorerView, InternalPlugin } from 'obsidian-typings'; import { FOLDER_OVERVIEW_VIEW, FolderOverviewView } from './obsidian-folder-overview/src/view'; import { registerOverviewCommands } from './obsidian-folder-overview/src/Commands'; import { updateOverviewView, updateViewDropdown } from './obsidian-folder-overview/src/main'; @@ -51,9 +50,6 @@ export default class FolderNotesPlugin extends Plugin { askModalCurrentlyOpen = false; fvIndexDB: FvIndexDB; - private fileExplorerPlugin!: InternalPlugin; - private fileExplorerView!: FileExplorerView; - async onload(): Promise { console.log('loading folder notes plugin'); await this.loadSettings(); @@ -175,6 +171,10 @@ export default class FolderNotesPlugin extends Plugin { return new FolderOverviewView(leaf, this); }); + this.app.workspace.on('layout-change', () => { + this.tabManager.updateTabs(); + }); + if (this.app.plugins.getPlugin('obsidian-front-matter-title-plugin')) { this.fmtpHandler = new FrontMatterTitlePluginHandler(this); } From 88cb9541f09054a6770bbd76ca38cc3d830f4970 Mon Sep 17 00:00:00 2001 From: mjkerrison <25721638+mjkerrison@users.noreply.github.com> Date: Thu, 8 Jan 2026 12:35:49 +1100 Subject: [PATCH 44/47] fix: prevent excluded folders list from being reset The filter logic in deleteFolderNote() and hideFolderNoteInFileExplorer() was using && instead of ||, causing all excluded folders with showFolderNote=false (the default) to be removed instead of just the target entry. Fixes #293 Co-Authored-By: Claude Opus 4.5 --- src/functions/folderNoteFunctions.ts | 2 +- src/functions/styleFunctions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/functions/folderNoteFunctions.ts b/src/functions/folderNoteFunctions.ts index 69e1830..e91d750 100644 --- a/src/functions/folderNoteFunctions.ts +++ b/src/functions/folderNoteFunctions.ts @@ -410,7 +410,7 @@ export async function deleteFolderNote( if (!folder) return; plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter( - (excludedFolder) => (excludedFolder.path !== folder.path) && excludedFolder.showFolderNote); + (excludedFolder) => (excludedFolder.path !== folder.path) || !excludedFolder.showFolderNote); plugin.saveSettings(false); removeCSSClassFromFileExplorerEL(folder.path, 'has-folder-note', false, plugin); diff --git a/src/functions/styleFunctions.ts b/src/functions/styleFunctions.ts index a99c6b8..7959702 100644 --- a/src/functions/styleFunctions.ts +++ b/src/functions/styleFunctions.ts @@ -226,7 +226,7 @@ export function showFolderNoteInFileExplorer(path: string, plugin: FolderNotesPl export function hideFolderNoteInFileExplorer(folderPath: string, plugin: FolderNotesPlugin): void { plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter( - (folder) => (folder.path !== folderPath) && folder.showFolderNote); + (folder) => (folder.path !== folderPath) || !folder.showFolderNote); plugin.saveSettings(false); removeCSSClassFromFileExplorerEL(folderPath, 'show-folder-note-in-explorer', true, plugin); updateCSSClassesForFolder(folderPath, plugin); From a044e6c2eb19d7e08e9a4e6e6b28ac0f182f710e Mon Sep 17 00:00:00 2001 From: mjkerrison <25721638+mjkerrison@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:22:28 +1100 Subject: [PATCH 45/47] fix: startup error and settings tab reset issues - Handle missing file explorer during early startup to prevent "Cannot read properties of undefined" error - Use renderSettingsPage instead of display when adding excluded/ whitelisted folders to stay on current settings tab Co-Authored-By: Claude Opus 4.5 --- .../modals/WhitelistedFoldersSettings.ts | 2 +- src/functions/styleFunctions.ts | 6 ++++-- src/functions/utils.ts | 17 ++++++++++------- src/settings/ExcludedFoldersSettings.ts | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts b/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts index b00342d..43d5cce 100644 --- a/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts +++ b/src/ExcludeFolders/modals/WhitelistedFoldersSettings.ts @@ -40,7 +40,7 @@ export default class WhitelistedFoldersSettings extends Modal { this.plugin.settingsTab, contentEl, whitelistedFolder, ); addWhitelistedFolder(this.plugin, whitelistedFolder); - this.settingsTab.display(); + this.settingsTab.renderSettingsPage(this.settingsTab.plugin.settings.settingsTab); }); }); diff --git a/src/functions/styleFunctions.ts b/src/functions/styleFunctions.ts index 7959702..4e99d42 100644 --- a/src/functions/styleFunctions.ts +++ b/src/functions/styleFunctions.ts @@ -14,8 +14,10 @@ import type FolderOverviewPlugin from 'src/obsidian-folder-overview/src/main'; * @description Refreshes the CSS classes for all folder notes in the file explorer. */ export function refreshAllFolderStyles(forceReload = false, plugin: FolderNotesPlugin): void { - if (plugin.activeFileExplorer === getFileExplorer(plugin) && !forceReload) { return; } - plugin.activeFileExplorer = getFileExplorer(plugin); + const fileExplorer = getFileExplorer(plugin); + if (!fileExplorer) { return; } + if (plugin.activeFileExplorer === fileExplorer && !forceReload) { return; } + plugin.activeFileExplorer = fileExplorer; plugin.app.vault.getAllLoadedFiles().forEach(async (file) => { if (file instanceof TFolder) { await updateCSSClassesForFolder(file.path, plugin); diff --git a/src/functions/utils.ts b/src/functions/utils.ts index cca1363..be765f2 100644 --- a/src/functions/utils.ts +++ b/src/functions/utils.ts @@ -42,15 +42,17 @@ export function getParentFolderPath(path: string): string { export function getFileExplorer( plugin: FolderNotesPlugin | FolderOverviewPlugin, -): FileExplorerWorkspaceLeaf { +): FileExplorerWorkspaceLeaf | undefined { // eslint-disable-next-line max-len let leaf = plugin.app.workspace.getLeavesOfType('file-explorer')[0] as unknown as FileExplorerWorkspaceLeaf; + if (!leaf) { return undefined; } + /* make.md plugin integration */ - if (leaf.containerEl.lastChild.dataset.type == 'mk-path-view') { + if ((leaf.containerEl?.lastChild as HTMLElement)?.dataset?.type == 'mk-path-view') { plugin.app.workspace.iterateAllLeaves((x) => { - if (x.tabHeaderEl.dataset.type == 'file-explorer') { - leaf = x; + if ((x as FileExplorerWorkspaceLeaf).tabHeaderEl?.dataset?.type == 'file-explorer') { + leaf = x as FileExplorerWorkspaceLeaf; } }); } @@ -58,12 +60,13 @@ export function getFileExplorer( return leaf; } -export function getFileExplorerView(plugin: FolderNotesPlugin): FileExplorerView { - return getFileExplorer(plugin).view; +export function getFileExplorerView(plugin: FolderNotesPlugin): FileExplorerView | undefined { + return getFileExplorer(plugin)?.view; } export function getFocusedItem(plugin: FolderNotesPlugin): TreeNode | null { - const fileExplorer = getFileExplorer(plugin) as unknown as FileExplorerLeaf; + const fileExplorer = getFileExplorer(plugin) as unknown as FileExplorerLeaf | undefined; + if (!fileExplorer) { return null; } const { focusedItem } = fileExplorer.view.tree; return focusedItem; } diff --git a/src/settings/ExcludedFoldersSettings.ts b/src/settings/ExcludedFoldersSettings.ts index b8b9345..55e5c7e 100644 --- a/src/settings/ExcludedFoldersSettings.ts +++ b/src/settings/ExcludedFoldersSettings.ts @@ -93,7 +93,7 @@ export async function renderExcludeFolders(settingsTab: SettingsTab): Promise Date: Wed, 28 Jan 2026 12:27:22 +0100 Subject: [PATCH 46/47] Fix #296 --- styles.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/styles.css b/styles.css index a8a114b..1466d0d 100644 --- a/styles.css +++ b/styles.css @@ -23,6 +23,9 @@ cursor: pointer !important; } +.hide-folder-note :not(.show-folder-note-in-explorer).only-has-folder-note .nav-folder-children { + display: none !important; +} /* ========================================================================== Tree Items From 7c41751c34b43b2863ae4358a8942b4114d2a382 Mon Sep 17 00:00:00 2001 From: Paul <70213368+LostPaul@users.noreply.github.com> Date: Sun, 1 Feb 2026 19:47:00 +0100 Subject: [PATCH 47/47] Update manifest.json --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index ad3738c..94ead43 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes", - "version": "1.8.17", + "version": "1.8.18", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul",