From 0469221b90c42edd60ce105bd6c872aa9e5e3187 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Wed, 15 Mar 2023 21:02:00 +0100 Subject: [PATCH 1/7] Added more setting options --- src/commands.ts | 12 ++ src/main.ts | 15 ++- src/settings.ts | 47 +++++++- src/suggesters/FileSuggester.ts | 54 +++++++++ src/suggesters/suggest.ts | 202 ++++++++++++++++++++++++++++++++ styles.css | 4 + 6 files changed, 327 insertions(+), 7 deletions(-) create mode 100644 src/commands.ts create mode 100644 src/suggesters/FileSuggester.ts create mode 100644 src/suggesters/suggest.ts diff --git a/src/commands.ts b/src/commands.ts new file mode 100644 index 0000000..5cde0c9 --- /dev/null +++ b/src/commands.ts @@ -0,0 +1,12 @@ +import { App } from 'obsidian'; +import FolderNotesPlugin from './main'; +export class Commands { + plugin: FolderNotesPlugin; + app: App; + constructor(app: App, plugin: FolderNotesPlugin) { + this.plugin = plugin; + this.app = app; + } + registerCommands() { + } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 4999698..f9f476f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,6 +11,7 @@ export default class FolderNotesPlugin extends Plugin { await this.loadSettings(); this.settingsTab = new SettingsTab(this.app, this); this.addSettingTab(this.settingsTab); + document.body.classList.add('folder-notes-plugin') if (this.settings.hideFolderNote) { document.body.classList.add('hide-folder-note'); } else { @@ -24,13 +25,12 @@ export default class FolderNotesPlugin extends Plugin { if (!path) return; const folder = this.app.vault.getAbstractFileByPath(path); if (folder) return; - this.createFolderNote(path); - + this.createFolderNote(path, true); } })); this.registerEvent(this.app.vault.on('rename', (file: TAbstractFile, oldPath: string) => { - if (!this.settings.autoRename) return; + if (!this.settings.syncFolderName) return; if (file instanceof TFolder) { const folder = this.app.vault.getAbstractFileByPath(file?.path); const oldName = oldPath.substring(oldPath.lastIndexOf('/' || '\\')); @@ -70,6 +70,11 @@ export default class FolderNotesPlugin extends Plugin { async handleFolderClick(event: MouseEvent) { if (!(event.target instanceof HTMLElement)) return; event.stopImmediatePropagation(); + if (!document.body.classList.contains('folder-notes-plugin')) { + event.target.onclick = null; + event.target.click(); + return; + } const folder = event.target.parentElement?.getAttribute('data-path'); const path = folder + '/' + event.target.innerText + '.md'; @@ -104,11 +109,12 @@ export default class FolderNotesPlugin extends Plugin { } } - async createFolderNote(path: string) { + async createFolderNote(path: string, useModal?: boolean) { const leaf = this.app.workspace.getLeaf(false); const file = await this.app.vault.create(path, ''); await leaf.openFile(file); if (!this.settings.autoCreate) return; + if (!useModal) return; const folder = this.app.vault.getAbstractFileByPath(path.substring(0, path.lastIndexOf('/' || '\\'))); if (!(folder instanceof TFolder)) return; const modal = new FolderNameModal(this.app, this, folder); @@ -126,6 +132,7 @@ export default class FolderNotesPlugin extends Plugin { onunload() { console.log('unloading folder notes plugin'); this.observer.disconnect(); + document.body.classList.remove('folder-notes-plugin'); } async loadSettings() { diff --git a/src/settings.ts b/src/settings.ts index 32af903..006bee5 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -4,19 +4,19 @@ export interface FolderNotesSettings { syncFolderName: boolean; ctrlKey: boolean; altKey: boolean; - autoRename: boolean; hideFolderNote: boolean; templatePath: string; autoCreate: boolean; + excludeFolders: string[]; } export const DEFAULT_SETTINGS: FolderNotesSettings = { syncFolderName: true, ctrlKey: true, altKey: false, - autoRename: true, hideFolderNote: true, templatePath: '', - autoCreate: true, + autoCreate: false, + excludeFolders: [], }; export class SettingsTab extends PluginSettingTab { plugin: FolderNotesPlugin; @@ -48,5 +48,46 @@ export class SettingsTab extends PluginSettingTab { this.display(); }) ); + new Setting(containerEl) + .setName('Sync folder name') + .setDesc('Automatically rename the folder note when the folder name is changed') + .addToggle((toggle) => + toggle + .setValue(this.plugin.settings.syncFolderName) + .onChange(async (value) => { + this.plugin.settings.syncFolderName = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + new Setting(containerEl) + .setName('Auto create folder note') + .setDesc('Automatically create a folder note when a new folder is created') + .addToggle((toggle) => + toggle + .setValue(this.plugin.settings.autoCreate) + .onChange(async (value) => { + this.plugin.settings.autoCreate = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + new Setting(containerEl) + .setName('Key for creating folder note') + .setDesc('The key combination to create a folder note') + .addDropdown((dropdown) => { + dropdown + .addOption('ctrl', 'Ctrl + Click') + .addOption('alt', 'Alt + Click') + .setValue(this.plugin.settings.ctrlKey ? 'ctrl' : 'alt') + .onChange(async (value) => { + this.plugin.settings.ctrlKey = value === 'ctrl'; + this.plugin.settings.altKey = value === 'alt'; + await this.plugin.saveSettings(); + this.display(); + }); + }); + + } } \ No newline at end of file diff --git a/src/suggesters/FileSuggester.ts b/src/suggesters/FileSuggester.ts new file mode 100644 index 0000000..c552642 --- /dev/null +++ b/src/suggesters/FileSuggester.ts @@ -0,0 +1,54 @@ +// 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 { TextInputSuggest } from "./suggest"; +import FolderNotesPlugin from "../main"; +export enum FileSuggestMode { + TemplateFiles, + ScriptFiles, +} + +export class FileSuggest extends TextInputSuggest { + constructor( + public inputEl: HTMLInputElement, + private plugin: FolderNotesPlugin + ) { + super(inputEl); + } + + + get_error_msg(mode: FileSuggestMode): string { + switch (mode) { + case FileSuggestMode.TemplateFiles: + return `Templates folder doesn't exist`; + case FileSuggestMode.ScriptFiles: + return `User Scripts folder doesn't exist`; + } + } + + getSuggestions(input_str: string): TFile[] { + const files: TFile[] = []; + const lower_input_str = input_str.toLowerCase(); + + this.plugin.app.vault.getFiles().forEach((file: TAbstractFile) => { + if ( + file instanceof TFile && + file.path.toLowerCase().contains(lower_input_str) + ) { + files.push(file); + } + }); + + return files; + } + + renderSuggestion(file: TFile, el: HTMLElement): void { + el.setText(file.path); + } + + selectSuggestion(file: TFile): void { + this.inputEl.value = file.path; + this.inputEl.trigger("input"); + this.close(); + } +} \ No newline at end of file diff --git a/src/suggesters/suggest.ts b/src/suggesters/suggest.ts new file mode 100644 index 0000000..5e03bc9 --- /dev/null +++ b/src/suggesters/suggest.ts @@ -0,0 +1,202 @@ +// 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"; + +const wrapAround = (value: number, size: number): number => { + return ((value % size) + size) % size; +}; + +class Suggest { + private owner: ISuggestOwner; + private values: T[]; + private suggestions: HTMLDivElement[]; + private selectedItem: number; + private containerEl: HTMLElement; + + constructor( + owner: ISuggestOwner, + containerEl: HTMLElement, + scope: Scope + ) { + this.owner = owner; + this.containerEl = containerEl; + + containerEl.on( + "click", + ".suggestion-item", + this.onSuggestionClick.bind(this) + ); + containerEl.on( + "mousemove", + ".suggestion-item", + this.onSuggestionMouseover.bind(this) + ); + + scope.register([], "ArrowUp", (event) => { + if (!event.isComposing) { + this.setSelectedItem(this.selectedItem - 1, true); + return false; + } + }); + + scope.register([], "ArrowDown", (event) => { + if (!event.isComposing) { + this.setSelectedItem(this.selectedItem + 1, true); + return false; + } + }); + + scope.register([], "Enter", (event) => { + if (!event.isComposing) { + this.useSelectedItem(event); + return false; + } + }); + } + + onSuggestionClick(event: MouseEvent, el: HTMLDivElement): void { + event.preventDefault(); + + const item = this.suggestions.indexOf(el); + this.setSelectedItem(item, false); + this.useSelectedItem(event); + } + + onSuggestionMouseover(_event: MouseEvent, el: HTMLDivElement): void { + const item = this.suggestions.indexOf(el); + this.setSelectedItem(item, false); + } + + setSuggestions(values: T[]) { + this.containerEl.empty(); + const suggestionEls: HTMLDivElement[] = []; + + values.forEach((value) => { + const suggestionEl = this.containerEl.createDiv("suggestion-item"); + this.owner.renderSuggestion(value, suggestionEl); + suggestionEls.push(suggestionEl); + }); + + this.values = values; + this.suggestions = suggestionEls; + this.setSelectedItem(0, false); + } + + useSelectedItem(event: MouseEvent | KeyboardEvent) { + const currentValue = this.values[this.selectedItem]; + if (currentValue) { + this.owner.selectSuggestion(currentValue, event); + } + } + + setSelectedItem(selectedIndex: number, scrollIntoView: boolean) { + const normalizedIndex = wrapAround( + selectedIndex, + this.suggestions.length + ); + const prevSelectedSuggestion = this.suggestions[this.selectedItem]; + const selectedSuggestion = this.suggestions[normalizedIndex]; + + prevSelectedSuggestion?.removeClass("is-selected"); + selectedSuggestion?.addClass("is-selected"); + + this.selectedItem = normalizedIndex; + + if (scrollIntoView) { + selectedSuggestion.scrollIntoView(false); + } + } +} + +export abstract class TextInputSuggest implements ISuggestOwner { + protected inputEl: HTMLInputElement | HTMLTextAreaElement; + + private popper: PopperInstance; + private scope: Scope; + private suggestEl: HTMLElement; + private suggest: Suggest; + + constructor(inputEl: HTMLInputElement | HTMLTextAreaElement) { + this.inputEl = inputEl; + this.scope = new Scope(); + + this.suggestEl = createDiv("suggestion-container"); + const suggestion = this.suggestEl.createDiv("suggestion"); + this.suggest = new Suggest(this, suggestion, this.scope); + + this.scope.register([], "Escape", this.close.bind(this)); + + this.inputEl.addEventListener("input", this.onInputChanged.bind(this)); + this.inputEl.addEventListener("focus", this.onInputChanged.bind(this)); + this.inputEl.addEventListener("blur", this.close.bind(this)); + this.suggestEl.on( + "mousedown", + ".suggestion-container", + (event: MouseEvent) => { + event.preventDefault(); + } + ); + } + + onInputChanged(): void { + const inputStr = this.inputEl.value; + const suggestions = this.getSuggestions(inputStr); + + if (!suggestions) { + this.close(); + return; + } + + if (suggestions.length > 0) { + this.suggest.setSuggestions(suggestions); + // @ts-ignore + this.open(app.dom.appContainerEl, this.inputEl); + } else { + this.close(); + } + } + + open(container: HTMLElement, inputEl: HTMLElement): void { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + app.keymap.pushScope(this.scope); + + container.appendChild(this.suggestEl); + this.popper = createPopper(inputEl, this.suggestEl, { + placement: "bottom-start", + modifiers: [ + { + name: "sameWidth", + enabled: true, + fn: ({ state, instance }) => { + // 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 + // we need to early exit to avoid an infinite loop + const targetWidth = `${state.rects.reference.width}px`; + if (state.styles.popper.width === targetWidth) { + return; + } + state.styles.popper.width = targetWidth; + instance.update(); + }, + phase: "beforeWrite", + requires: ["computeStyles"], + }, + ], + }); + } + + close(): void { + app.keymap.popScope(this.scope); + + this.suggest.setSuggestions([]); + if (this.popper) this.popper.destroy(); + this.suggestEl.detach(); + } + + abstract getSuggestions(inputStr: string): T[]; + abstract renderSuggestion(item: T, el: HTMLElement): void; + abstract selectSuggestion(item: T): void; +} \ No newline at end of file diff --git a/styles.css b/styles.css index bb0c880..53265a7 100644 --- a/styles.css +++ b/styles.css @@ -10,4 +10,8 @@ .hide-folder-note .is-folder-note { display: none; +} + +.nav-folder-collapse-indicator:hover { + cursor: pointer; } \ No newline at end of file From ab91d14f676951b286fcab2d0b77ad93676c2f98 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Thu, 16 Mar 2023 12:57:42 +0100 Subject: [PATCH 2/7] Update main.ts --- src/main.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.ts b/src/main.ts index f9f476f..24cd1e3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -45,6 +45,7 @@ export default class FolderNotesPlugin extends Plugin { } } else if (file instanceof TFile) { const folder = this.app.vault.getAbstractFileByPath(oldPath.substring(0, oldPath.lastIndexOf('/' || '\\'))); + if (file.name !== folder?.name + '.md') return; if (folder instanceof TFolder) { this.app.vault.rename(folder, folder.path.substring(0, folder.path.lastIndexOf('/' || '\\')) + '/' + file.name.substring(0, file.name.lastIndexOf('.'))); } From 0f355c846a4f4de4f3fed467ad9cc981226dabd9 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Thu, 16 Mar 2023 19:45:02 +0100 Subject: [PATCH 3/7] Update settings.ts --- src/settings.ts | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/settings.ts b/src/settings.ts index 006bee5..dc5103e 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -9,6 +9,14 @@ export interface FolderNotesSettings { autoCreate: boolean; excludeFolders: string[]; } +export interface ExcludeFolder { + path: string; + subFolders: boolean; + exludeSync: boolean; + excludeAutoCreate: boolean; + disableFolderNote: boolean; + position: number; +} export const DEFAULT_SETTINGS: FolderNotesSettings = { syncFolderName: true, ctrlKey: true, @@ -88,6 +96,23 @@ export class SettingsTab extends PluginSettingTab { }); }); - + new Setting(containerEl) + .setHeading() + .setName('Manage excluded folders') + new Setting(containerEl) + .setName('Add excluded folder') + .addButton(cb => { + cb.setIcon('plus'); + cb.setClass('add-exclude-folder'); + cb.setTooltip('Add excluded folder'); + cb.onClick(() => { + }) + }) + } + addExcludeFolderListItem(excludeFolder: ExcludeFolder) { + const { containerEl } = this; + new Setting(containerEl) + } + addExcludeFolder(excludeFolder: ExcludeFolder) { } } \ No newline at end of file From 8f134b46b0d0019f87b8b07dce8930bbfef93f48 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Thu, 16 Mar 2023 22:07:30 +0100 Subject: [PATCH 4/7] Plugin settings progress --- package.json | 3 + src/main.ts | 2 +- src/modals/exludeFolderSettings.ts | 34 +++++ .../folderName.ts} | 2 +- src/settings.ts | 117 ++++++++++++++++-- .../{FileSuggester.ts => FolderSuggester.ts} | 28 ++--- 6 files changed, 157 insertions(+), 29 deletions(-) create mode 100644 src/modals/exludeFolderSettings.ts rename src/{folderNameModal.ts => modals/folderName.ts} (96%) rename src/suggesters/{FileSuggester.ts => FolderSuggester.ts} (56%) diff --git a/package.json b/package.json index 4f771da..cdd8d82 100644 --- a/package.json +++ b/package.json @@ -20,5 +20,8 @@ "obsidian": "latest", "tslib": "2.4.0", "typescript": "4.7.4" + }, + "dependencies": { + "@popperjs/core": "^2.11.6" } } diff --git a/src/main.ts b/src/main.ts index 24cd1e3..d427623 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ import { Plugin, TFile, TFolder, TAbstractFile } from 'obsidian' import { DEFAULT_SETTINGS, FolderNotesSettings, SettingsTab } from './settings' -import FolderNameModal from './folderNameModal'; +import FolderNameModal from './modals/folderName'; export default class FolderNotesPlugin extends Plugin { observer: MutationObserver folders: TFolder[] = [] diff --git a/src/modals/exludeFolderSettings.ts b/src/modals/exludeFolderSettings.ts new file mode 100644 index 0000000..b68a8d2 --- /dev/null +++ b/src/modals/exludeFolderSettings.ts @@ -0,0 +1,34 @@ +import { App, Modal, Setting } from 'obsidian'; +import FolderNotesPlugin from '../main'; +import { ExcludedFolder } from '../settings'; +export default class ExcludedFolderSettings extends Modal { + plugin: FolderNotesPlugin; + app: App; + excludedFolder: ExcludedFolder; + constructor(app: App, plugin: FolderNotesPlugin, excludedFolder: ExcludedFolder) { + super(app); + this.plugin = plugin; + this.app = app; + this.excludedFolder = excludedFolder; + } + onOpen() { + const { contentEl } = this; + contentEl.createEl('h2', { text: 'Exluded folder settings' }); + new Setting(contentEl) + .setName('Include subfolders') + .setDesc('Choose if subfolders of the folder should also be excluded') + .addToggle((toggle) => + toggle + .setValue(this.excludedFolder.subFolders) + .onChange(async (value) => { + this.excludedFolder.subFolders = value; + await this.plugin.saveSettings(); + }) + ); + + } + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +} \ No newline at end of file diff --git a/src/folderNameModal.ts b/src/modals/folderName.ts similarity index 96% rename from src/folderNameModal.ts rename to src/modals/folderName.ts index 2d0337a..0ce65d8 100644 --- a/src/folderNameModal.ts +++ b/src/modals/folderName.ts @@ -1,5 +1,5 @@ import { App, Modal, Setting, TFolder } from 'obsidian'; -import FolderNotesPlugin from './main'; +import FolderNotesPlugin from '../main'; export default class FolderNameModal extends Modal { plugin: FolderNotesPlugin; app: App; diff --git a/src/settings.ts b/src/settings.ts index dc5103e..e84336e 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,5 +1,7 @@ import { App, PluginSettingTab, Setting } from "obsidian"; import FolderNotesPlugin from "./main"; +import { FolderSuggest } from "./suggesters/FolderSuggester"; +import ExcludedFolderSettings from "./modals/exludeFolderSettings"; export interface FolderNotesSettings { syncFolderName: boolean; ctrlKey: boolean; @@ -7,16 +9,9 @@ export interface FolderNotesSettings { hideFolderNote: boolean; templatePath: string; autoCreate: boolean; - excludeFolders: string[]; -} -export interface ExcludeFolder { - path: string; - subFolders: boolean; - exludeSync: boolean; - excludeAutoCreate: boolean; - disableFolderNote: boolean; - position: number; + excludeFolders: ExcludedFolder[]; } + export const DEFAULT_SETTINGS: FolderNotesSettings = { syncFolderName: true, ctrlKey: true, @@ -29,6 +24,7 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = { export class SettingsTab extends PluginSettingTab { plugin: FolderNotesPlugin; app: App; + excludeFolders: ExcludedFolder[]; constructor(app: App, plugin: FolderNotesPlugin) { super(app, plugin); } @@ -106,13 +102,108 @@ export class SettingsTab extends PluginSettingTab { cb.setClass('add-exclude-folder'); cb.setTooltip('Add excluded folder'); cb.onClick(() => { + const excludedFolder = new ExcludedFolder('', true, true, true, false, this.plugin.settings.excludeFolders.length); + this.addExcludeFolderListItem(containerEl, excludedFolder); + this.addExcludedFolder(excludedFolder); + this.display(); }) }) + this.plugin.settings.excludeFolders.sort((a, b) => a.position - b.position).forEach((excludedFolder) => { + this.addExcludeFolderListItem(containerEl, excludedFolder); + }) } - addExcludeFolderListItem(excludeFolder: ExcludeFolder) { - const { containerEl } = this; - new Setting(containerEl) + addExcludeFolderListItem(containerEl: HTMLElement, excludedFolder: ExcludedFolder) { + const setting = new Setting(containerEl) + setting.addSearch(cb => { + new FolderSuggest( + cb.inputEl, + this.plugin + ); + cb.setPlaceholder('Folder path'); + cb.setValue(excludedFolder.path); + cb.onChange((value) => { + if (!this.app.vault.getAbstractFileByPath(value)) return; + excludedFolder.path = value; + this.updateExcludedFolder(excludedFolder, excludedFolder); + }) + }) + setting.addButton(cb => { + cb.setIcon('edit'); + cb.setTooltip('Edit folder note'); + cb.onClick(() => { + new ExcludedFolderSettings(this.app, this.plugin, excludedFolder).open(); + }) + }) + + setting.addButton(cb => { + cb.setIcon('up-chevron-glyph'); + cb.setTooltip('Move up'); + cb.onClick(() => { + if (excludedFolder.position === 0) return; + excludedFolder.position = excludedFolder.position - 1; + console.log(excludedFolder.position); + this.updateExcludedFolder(excludedFolder, excludedFolder); + const oldExcludedFolder = this.plugin.settings.excludeFolders.find(folder => folder.position == excludedFolder.position) + if (oldExcludedFolder) { + + oldExcludedFolder.position = oldExcludedFolder.position + 1; + this.updateExcludedFolder(oldExcludedFolder, oldExcludedFolder); + } + this.display(); + }) + }) + setting.addButton(cb => { + cb.setIcon('down-chevron-glyph'); + cb.setTooltip('Move down'); + cb.onClick(() => { + if (excludedFolder.position === this.plugin.settings.excludeFolders.length - 1) return; + excludedFolder.position = excludedFolder.position + 1; + this.updateExcludedFolder(excludedFolder, excludedFolder); + const oldExcludedFolder = this.plugin.settings.excludeFolders.find(folder => folder.position == excludedFolder.position) + if (oldExcludedFolder) { + oldExcludedFolder.position = oldExcludedFolder.position - 1; + this.updateExcludedFolder(oldExcludedFolder, oldExcludedFolder); + } + this.display(); + }) + }) + setting.addButton(cb => { + cb.setIcon('trash-2'); + cb.setTooltip('Delete excluded folder'); + cb.onClick(() => { + this.deleteExcludedFolder(excludedFolder); + setting.clear(); + setting.settingEl.remove(); + }) + }) } - addExcludeFolder(excludeFolder: ExcludeFolder) { + addExcludedFolder(excludedFolder: ExcludedFolder) { + this.plugin.settings.excludeFolders.push(excludedFolder); + this.plugin.saveSettings(); + } + deleteExcludedFolder(excludedFolder: ExcludedFolder) { + this.plugin.settings.excludeFolders = this.plugin.settings.excludeFolders.filter((folder) => folder.path !== excludedFolder.path); + this.plugin.saveSettings(); + } + updateExcludedFolder(excludedFolder: ExcludedFolder, newExcludeFolder: ExcludedFolder) { + this.plugin.settings.excludeFolders = this.plugin.settings.excludeFolders.filter((folder) => folder.path !== excludedFolder.path); + this.addExcludedFolder(newExcludeFolder); + } + +} +export class ExcludedFolder { + path: string; + subFolders: boolean; + exludeSync: boolean; + excludeAutoCreate: boolean; + disableFolderNote: boolean; + position: number; + constructor(path: string, subFolders: boolean, exludeSync: boolean, excludeAutoCreate: boolean, disableFolderNote: boolean, position: number) { + this.path = path; + this.subFolders = subFolders; + this.exludeSync = exludeSync; + this.excludeAutoCreate = excludeAutoCreate; + this.disableFolderNote = disableFolderNote; + this.position = position; } } \ No newline at end of file diff --git a/src/suggesters/FileSuggester.ts b/src/suggesters/FolderSuggester.ts similarity index 56% rename from src/suggesters/FileSuggester.ts rename to src/suggesters/FolderSuggester.ts index c552642..7660b32 100644 --- a/src/suggesters/FileSuggester.ts +++ b/src/suggesters/FolderSuggester.ts @@ -1,6 +1,6 @@ // 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 { TAbstractFile, TFolder } from "obsidian"; import { TextInputSuggest } from "./suggest"; import FolderNotesPlugin from "../main"; export enum FileSuggestMode { @@ -8,7 +8,7 @@ export enum FileSuggestMode { ScriptFiles, } -export class FileSuggest extends TextInputSuggest { +export class FolderSuggest extends TextInputSuggest { constructor( public inputEl: HTMLInputElement, private plugin: FolderNotesPlugin @@ -26,28 +26,28 @@ export class FileSuggest extends TextInputSuggest { } } - getSuggestions(input_str: string): TFile[] { - const files: TFile[] = []; + getSuggestions(input_str: string): TFolder[] { + const folders: TFolder[] = []; const lower_input_str = input_str.toLowerCase(); - - this.plugin.app.vault.getFiles().forEach((file: TAbstractFile) => { + this.plugin.app.vault.getAllLoadedFiles().forEach((folder: TAbstractFile) => { if ( - file instanceof TFile && - file.path.toLowerCase().contains(lower_input_str) + folder instanceof TFolder && + folder.path.toLowerCase().contains(lower_input_str) && + !this.plugin.settings.excludeFolders.find(f => f.path === folder.path) ) { - files.push(file); + folders.push(folder); } }); - return files; + return folders; } - renderSuggestion(file: TFile, el: HTMLElement): void { - el.setText(file.path); + renderSuggestion(folder: TFolder, el: HTMLElement): void { + el.setText(folder.path); } - selectSuggestion(file: TFile): void { - this.inputEl.value = file.path; + selectSuggestion(folder: TFolder): void { + this.inputEl.value = folder.path; this.inputEl.trigger("input"); this.close(); } From c1b5e229a87041467aaacf3278807173941820f8 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Fri, 17 Mar 2023 22:58:27 +0100 Subject: [PATCH 5/7] Settings progress --- src/main.ts | 21 +++++++++++++-------- src/modals/exludeFolderSettings.ts | 3 +++ src/settings.ts | 12 +++++++----- styles.css | 16 ++++++++++++++++ 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/main.ts b/src/main.ts index d427623..d443125 100644 --- a/src/main.ts +++ b/src/main.ts @@ -17,16 +17,19 @@ export default class FolderNotesPlugin extends Plugin { } else { document.body.classList.remove('hide-folder-note'); } - this.registerEvent(this.app.vault.on('create', (file: TAbstractFile) => { + this.registerEvent(this.app.vault.on('create', (folder: TAbstractFile) => { if (!this.app.workspace.layoutReady) return; if (!this.settings.autoCreate) return; - if (file instanceof TFolder) { - const path = file.path + '/' + file.name + '.md'; - if (!path) return; - const folder = this.app.vault.getAbstractFileByPath(path); - if (folder) return; - this.createFolderNote(path, true); - } + if (!(folder instanceof TFolder)) return; + const excludedFolder = this.settings.excludeFolders.find((excludedFolder) => excludedFolder.path === folder.path); + if (excludedFolder?.disableAutoCreate) return; + + const path = folder.path + '/' + folder.name + '.md'; + if (!path) return; + const file = this.app.vault.getAbstractFileByPath(path); + if (file) return; + this.createFolderNote(path, true); + })); this.registerEvent(this.app.vault.on('rename', (file: TAbstractFile, oldPath: string) => { @@ -45,6 +48,8 @@ export default class FolderNotesPlugin extends Plugin { } } else if (file instanceof TFile) { const folder = this.app.vault.getAbstractFileByPath(oldPath.substring(0, oldPath.lastIndexOf('/' || '\\'))); + const excludedFolder = this.settings.excludeFolders.find((excludedFolder) => excludedFolder.path === folder?.path); + if (excludedFolder?.disableSync) return; if (file.name !== folder?.name + '.md') return; if (folder instanceof TFolder) { this.app.vault.rename(folder, folder.path.substring(0, folder.path.lastIndexOf('/' || '\\')) + '/' + file.name.substring(0, file.name.lastIndexOf('.'))); diff --git a/src/modals/exludeFolderSettings.ts b/src/modals/exludeFolderSettings.ts index b68a8d2..9f248f5 100644 --- a/src/modals/exludeFolderSettings.ts +++ b/src/modals/exludeFolderSettings.ts @@ -26,6 +26,9 @@ export default class ExcludedFolderSettings extends Modal { }) ); + new Setting(contentEl) + + } onClose() { const { contentEl } = this; diff --git a/src/settings.ts b/src/settings.ts index e84336e..6aa9a07 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -114,6 +114,7 @@ export class SettingsTab extends PluginSettingTab { } addExcludeFolderListItem(containerEl: HTMLElement, excludedFolder: ExcludedFolder) { const setting = new Setting(containerEl) + setting.setClass('fn-exclude-folder-list-item') setting.addSearch(cb => { new FolderSuggest( cb.inputEl, @@ -194,15 +195,16 @@ export class SettingsTab extends PluginSettingTab { export class ExcludedFolder { path: string; subFolders: boolean; - exludeSync: boolean; - excludeAutoCreate: boolean; + disableSync: boolean; + disableAutoCreate: boolean; disableFolderNote: boolean; + enableCollapsing: boolean; position: number; - constructor(path: string, subFolders: boolean, exludeSync: boolean, excludeAutoCreate: boolean, disableFolderNote: boolean, position: number) { + constructor(path: string, subFolders: boolean, disableSync: boolean, disableAutoCreate: boolean, disableFolderNote: boolean, position: number) { this.path = path; this.subFolders = subFolders; - this.exludeSync = exludeSync; - this.excludeAutoCreate = excludeAutoCreate; + this.disableSync = disableSync; + this.disableAutoCreate = disableAutoCreate; this.disableFolderNote = disableFolderNote; this.position = position; } diff --git a/styles.css b/styles.css index 53265a7..765519e 100644 --- a/styles.css +++ b/styles.css @@ -14,4 +14,20 @@ .nav-folder-collapse-indicator:hover { cursor: pointer; +} + +.fn-exclude-folder-list-item { + border-top: none; + float: left; + display: block; +} + +.fn-exclude-folder-list-item input { + width: 34.5rem; +} + +@media screen and (max-width: 1250px) { + .fn-exclude-folder-list-item input { + width: 100%; + } } \ No newline at end of file From d7b8af798946fafe082813bdf1cbd117b8f8510a Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sat, 18 Mar 2023 22:56:11 +0100 Subject: [PATCH 6/7] Settings progress --- package-lock.json | 1889 +++++++++++++++++++++++++++ src/main.ts | 73 +- src/modals/exludeFolderSettings.ts | 57 +- src/settings.ts | 37 +- src/suggesters/templateSuggester.ts | 70 + src/template.ts | 92 ++ styles.css | 23 +- 7 files changed, 2222 insertions(+), 19 deletions(-) create mode 100644 src/suggesters/templateSuggester.ts create mode 100644 src/template.ts diff --git a/package-lock.json b/package-lock.json index b94145f..65452c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "folder-notes", "version": "1.0.1", "license": "GPL-3.0-or-later", + "dependencies": { + "@popperjs/core": "^2.11.6" + }, "devDependencies": { "@types/node": "^16.11.6", "@typescript-eslint/eslint-plugin": "5.29.0", @@ -19,6 +22,121 @@ "typescript": "4.7.4" } }, + "node_modules/@codemirror/state": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", + "integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==", + "dev": true, + "peer": true + }, + "node_modules/@codemirror/view": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.9.2.tgz", + "integrity": "sha512-ci0r/v6aKOSlzOs7/STMTYP3jX/+YMq2dAfAJcLIB6uom4ThtrUlzeuS7GTRGNqJJ+qAJR1vGWfXgu4CO/0myQ==", + "dev": true, + "peer": true, + "dependencies": { + "@codemirror/state": "^6.1.4", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", + "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", + "dev": true, + "peer": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "dev": true, + "peer": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.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" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "peer": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@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, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "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==", + "dev": true, + "peer": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -54,6 +172,15 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@types/codemirror": { "version": "0.0.108", "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz", @@ -274,6 +401,79 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/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, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "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 + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -283,6 +483,24 @@ "node": ">=8" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "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==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -307,6 +525,75 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "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" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "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 + }, + "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 + }, + "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==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -324,6 +611,13 @@ } } }, + "node_modules/deep-is": { + "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 + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -336,6 +630,19 @@ "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/esbuild": { "version": "0.14.47", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.47.tgz", @@ -691,6 +998,77 @@ "node": ">=12" } }, + "node_modules/escape-string-regexp": { + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "dev": true, + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "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-sdsl": "^4.1.4", + "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" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -740,6 +1118,84 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "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/eslint/node_modules/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, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "dev": true, + "peer": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.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", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "peer": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "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", @@ -770,6 +1226,23 @@ "node": ">=4.0" } }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "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 + }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -786,6 +1259,20 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "peer": true + }, + "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 + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -795,6 +1282,19 @@ "reusify": "^1.0.4" } }, + "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==", + "dev": true, + "peer": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -807,12 +1307,78 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "peer": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "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==", + "dev": true, + "peer": true + }, + "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/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/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, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -825,6 +1391,22 @@ "node": ">= 6" } }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -845,6 +1427,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true, + "peer": true + }, + "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" + } + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -854,6 +1453,51 @@ "node": ">= 4" } }, + "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==", + "dev": true, + "peer": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "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", @@ -884,6 +1528,98 @@ "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 + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "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, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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 + }, + "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 + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "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 + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -918,6 +1654,19 @@ "node": ">=8.6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -933,6 +1682,13 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "peer": true + }, "node_modules/obsidian": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.1.1.tgz", @@ -947,6 +1703,109 @@ "@codemirror/view": "^6.0.0" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "peer": true, + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "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, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "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, + "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, + "engines": { + "node": ">=8" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -968,6 +1827,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prelude-ls": { + "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, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -1000,6 +1879,16 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/resolve-from": { + "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, + "engines": { + "node": ">=4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -1010,6 +1899,22 @@ "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/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -1048,6 +1953,29 @@ "node": ">=10" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "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, + "engines": { + "node": ">=8" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -1057,6 +1985,59 @@ "node": ">=8" } }, + "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, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==", + "dev": true, + "peer": true + }, + "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, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "peer": true + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1096,6 +2077,32 @@ "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, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "4.7.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", @@ -1109,14 +2116,164 @@ "node": ">=4.2.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==", + "dev": true, + "peer": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "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/yocto-queue": { + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { + "@codemirror/state": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", + "integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==", + "dev": true, + "peer": true + }, + "@codemirror/view": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.9.2.tgz", + "integrity": "sha512-ci0r/v6aKOSlzOs7/STMTYP3jX/+YMq2dAfAJcLIB6uom4ThtrUlzeuS7GTRGNqJJ+qAJR1vGWfXgu4CO/0myQ==", + "dev": true, + "peer": true, + "requires": { + "@codemirror/state": "^6.1.4", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", + "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", + "dev": true, + "peer": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true, + "peer": true + }, + "@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "dev": true, + "peer": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.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" + } + }, + "@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true, + "peer": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "peer": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@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 + }, + "@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 + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1143,6 +2300,11 @@ "fastq": "^1.6.0" } }, + "@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" + }, "@types/codemirror": { "version": "0.0.108", "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz", @@ -1274,12 +2436,82 @@ "eslint-visitor-keys": "^3.3.0" } }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "peer": 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": { + "version": "6.12.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", + "json-schema-traverse": "^0.4.1", + "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" + } + }, + "argparse": { + "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 + }, "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, + "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==", + "dev": true, + "peer": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -1295,6 +2527,60 @@ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "peer": 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" + } + }, + "color-convert": { + "version": "2.0.1", + "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" + } + }, + "color-name": { + "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 + }, + "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 + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1304,6 +2590,13 @@ "ms": "2.1.2" } }, + "deep-is": { + "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 + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1313,6 +2606,16 @@ "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==", + "dev": true, + "peer": true, + "requires": { + "esutils": "^2.0.2" + } + }, "esbuild": { "version": "0.14.47", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.47.tgz", @@ -1481,6 +2784,92 @@ "dev": true, "optional": true }, + "escape-string-regexp": { + "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 + }, + "eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "dev": true, + "peer": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "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-sdsl": "^4.1.4", + "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" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "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 + }, + "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" + } + } + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -1514,6 +2903,37 @@ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, + "espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "dev": true, + "peer": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esquery": { + "version": "1.5.0", + "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": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -1537,6 +2957,20 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "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 + }, + "fast-deep-equal": { + "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 + }, "fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -1550,6 +2984,20 @@ "micromatch": "^4.0.4" } }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "peer": 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 + }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -1559,6 +3007,16 @@ "reusify": "^1.0.4" } }, + "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==", + "dev": true, + "peer": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1568,12 +3026,63 @@ "to-regex-range": "^5.0.1" } }, + "find-up": { + "version": "5.0.0", + "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==", + "dev": true, + "peer": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "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 + }, + "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 + }, "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 }, + "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": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1583,6 +3092,16 @@ "is-glob": "^4.0.1" } }, + "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" + } + }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -1597,12 +3116,62 @@ "slash": "^3.0.0" } }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true, + "peer": 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 + }, "ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "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==", + "dev": true, + "peer": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "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 + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1624,6 +3193,79 @@ "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 + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "peer": 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" + } + }, + "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 + }, + "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 + }, + "levn": { + "version": "0.4.1", + "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" + } + }, + "locate-path": { + "version": "6.0.0", + "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" + } + }, + "lodash.merge": { + "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 + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1649,6 +3291,16 @@ "picomatch": "^2.3.1" } }, + "minimatch": { + "version": "3.1.2", + "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" + } + }, "moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -1661,6 +3313,13 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "peer": true + }, "obsidian": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.1.1.tgz", @@ -1671,6 +3330,82 @@ "moment": "2.29.4" } }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "peer": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "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" + } + }, + "p-limit": { + "version": "3.1.0", + "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" + } + }, + "p-locate": { + "version": "5.0.0", + "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" + } + }, + "parent-module": { + "version": "1.0.1", + "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" + } + }, + "path-exists": { + "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 + }, + "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 + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -1683,6 +3418,20 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "prelude-ls": { + "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 + }, + "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 + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -1695,12 +3444,29 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "resolve-from": { + "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 + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "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" + } + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -1719,12 +3485,70 @@ "lru-cache": "^6.0.0" } }, + "shebang-command": { + "version": "2.0.0", + "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" + } + }, + "shebang-regex": { + "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 + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": 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 + }, + "style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==", + "dev": true, + "peer": true + }, + "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, + "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", @@ -1757,17 +3581,82 @@ } } }, + "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, + "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==", "dev": true }, + "uri-js": { + "version": "4.4.1", + "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" + } + }, + "w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==", + "dev": true, + "peer": true + }, + "which": { + "version": "2.0.2", + "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" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "peer": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "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 + }, + "yocto-queue": { + "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 } } } diff --git a/src/main.ts b/src/main.ts index d443125..fb53894 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ import { Plugin, TFile, TFolder, TAbstractFile } from 'obsidian' import { DEFAULT_SETTINGS, FolderNotesSettings, SettingsTab } from './settings' import FolderNameModal from './modals/folderName'; +import { applyTemplate } from './template'; export default class FolderNotesPlugin extends Plugin { observer: MutationObserver folders: TFolder[] = [] @@ -21,7 +22,12 @@ export default class FolderNotesPlugin extends Plugin { if (!this.app.workspace.layoutReady) return; if (!this.settings.autoCreate) return; if (!(folder instanceof TFolder)) return; - const excludedFolder = this.settings.excludeFolders.find((excludedFolder) => excludedFolder.path === folder.path); + + const excludedFolder = this.settings.excludeFolders.find( + (excludedFolder) => (excludedFolder.path === + folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length)) || + (excludedFolder.path === folder?.path.slice(0, folder.path?.lastIndexOf("/")).slice(0, folder.path?.lastIndexOf("/")) + && excludedFolder.subFolders)); if (excludedFolder?.disableAutoCreate) return; const path = folder.path + '/' + folder.name + '.md'; @@ -82,7 +88,23 @@ export default class FolderNotesPlugin extends Plugin { return; } + const folder = event.target.parentElement?.getAttribute('data-path'); + const excludedFolder = this.settings.excludeFolders.find( + (excludedFolder) => (excludedFolder.path === folder?.slice(0, folder?.lastIndexOf("/") >= 0 ? folder?.lastIndexOf("/") : folder.length)) || + (excludedFolder.path === folder?.slice(0, folder?.lastIndexOf("/")).slice(0, folder?.lastIndexOf("/")) + && excludedFolder.subFolders)); + if (excludedFolder?.enableCollappsing && excludedFolder?.disableFolderNote) { + event.target.onclick = null; + event.target.click(); + return; + } else if (excludedFolder?.enableCollappsing) { + event.target.onclick = null; + event.target.click(); + event.target.onclick = (event: MouseEvent) => this.handFolderClickWithCollapse(event); + event.target.click(); + return; + } const path = folder + '/' + event.target.innerText + '.md'; if (this.app.vault.getAbstractFileByPath(path)) { @@ -115,10 +137,59 @@ export default class FolderNotesPlugin extends Plugin { } } + handFolderClickWithCollapse(event: MouseEvent) { + console.log(event) + if (!(event.target instanceof HTMLElement)) return; + if (!document.body.classList.contains('folder-notes-plugin')) { + event.target.onclick = null; + event.target.click(); + return; + } + console.log('handFolderClickWithCollapse') + + const folder = event.target.parentElement?.getAttribute('data-path'); + const path = folder + '/' + event.target.innerText + '.md'; + console.log(path) + + + if (this.app.vault.getAbstractFileByPath(path)) { + console.log('openFolderNote') + this.openFolderNote(path); + if (!this.settings.hideFolderNote) return; + event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file') + .forEach((element: HTMLElement) => { + if (element.innerText === (event.target as HTMLElement)?.innerText && !element.classList.contains('is-folder-note')) { + element.classList.add('is-folder-note'); + } + }); + + } else if (event.altKey || event.ctrlKey) { + console.log(event.altKey, event.ctrlKey); + if ((this.settings.altKey && event.altKey) || (this.settings.ctrlKey && event.ctrlKey)) { + this.createFolderNote(path); + if (!this.settings.hideFolderNote) return; + event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file') + .forEach((element: HTMLElement) => { + if (element.innerText === (event.target as HTMLElement)?.innerText && !element.classList.contains('is-folder-note')) { + element.classList.add('is-folder-note'); + } + }); + } else { + event.target.onclick = null; + event.target.click(); + } + } else { + console.log('click') + event.target.onclick = null; + event.target.click(); + } + } + async createFolderNote(path: string, useModal?: boolean) { const leaf = this.app.workspace.getLeaf(false); const file = await this.app.vault.create(path, ''); await leaf.openFile(file); + applyTemplate(this, this.settings.templatePath); if (!this.settings.autoCreate) return; if (!useModal) return; const folder = this.app.vault.getAbstractFileByPath(path.substring(0, path.lastIndexOf('/' || '\\'))); diff --git a/src/modals/exludeFolderSettings.ts b/src/modals/exludeFolderSettings.ts index 9f248f5..39b3287 100644 --- a/src/modals/exludeFolderSettings.ts +++ b/src/modals/exludeFolderSettings.ts @@ -12,11 +12,15 @@ export default class ExcludedFolderSettings extends Modal { this.excludedFolder = excludedFolder; } onOpen() { + this.display(); + } + display() { const { contentEl } = this; + contentEl.empty(); contentEl.createEl('h2', { text: 'Exluded folder settings' }); new Setting(contentEl) .setName('Include subfolders') - .setDesc('Choose if subfolders of the folder should also be excluded') + .setDesc('Choose if the subfolders of the folder should also be excluded') .addToggle((toggle) => toggle .setValue(this.excludedFolder.subFolders) @@ -27,7 +31,56 @@ export default class ExcludedFolderSettings extends Modal { ); new Setting(contentEl) - + .setName('Disable folder name sync') + .setDesc('Choose if the folder note should be renamed when the folder name is changed') + .addToggle((toggle) => + toggle + .setValue(this.excludedFolder.disableSync) + .onChange(async (value) => { + this.excludedFolder.disableSync = value; + await this.plugin.saveSettings(); + }) + ); + + new Setting(contentEl) + .setName('Disable auto creation of folder notes in this folder') + .setDesc('Choose if a folder note should be created when a new folder is created') + .addToggle((toggle) => + toggle + .setValue(this.excludedFolder.disableAutoCreate) + .onChange(async (value) => { + this.excludedFolder.disableAutoCreate = value; + await this.plugin.saveSettings(); + }) + ); + + + new Setting(contentEl) + .setName('Disable open folder note') + .setDesc('Choose if the folder note should be opened when the folder is opened') + .addToggle((toggle) => + toggle + .setValue(this.excludedFolder.disableFolderNote) + .onChange(async (value) => { + this.excludedFolder.disableFolderNote = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + + if (!this.excludedFolder.disableFolderNote) { + new Setting(contentEl) + .setName('Collapse folder when opening folder note') + .setDesc('Choose if the folder should be collapsed when the folder note is opened') + .addToggle((toggle) => + toggle + .setValue(this.excludedFolder.enableCollappsing) + .onChange(async (value) => { + this.excludedFolder.enableCollappsing = value; + await this.plugin.saveSettings(); + }) + ); + } } onClose() { diff --git a/src/settings.ts b/src/settings.ts index 6aa9a07..396e429 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,7 +1,8 @@ import { App, PluginSettingTab, Setting } from "obsidian"; import FolderNotesPlugin from "./main"; -import { FolderSuggest } from "./suggesters/FolderSuggester"; +import { FolderSuggest } from "./suggesters/folderSuggester"; import ExcludedFolderSettings from "./modals/exludeFolderSettings"; +import { TemplateSuggest } from "./suggesters/templateSuggester"; export interface FolderNotesSettings { syncFolderName: boolean; ctrlKey: boolean; @@ -92,6 +93,23 @@ export class SettingsTab extends PluginSettingTab { }); }); + new Setting(containerEl) + .setName('Template path') + .setDesc('The path to the template file') + .addSearch((cb) => { + new TemplateSuggest(cb.inputEl, this.plugin); + cb.setPlaceholder('Template path'); + cb.setValue(this.plugin.app.vault.getAbstractFileByPath(this.plugin.settings.templatePath)?.name.replace('.md', '') || ''); + cb.onChange(async (value) => { + if (value.trim() === '') { + this.plugin.settings.templatePath = ''; + await this.plugin.saveSettings(); + this.display(); + return; + } + }); + }); + new Setting(containerEl) .setHeading() .setName('Manage excluded folders') @@ -102,7 +120,7 @@ export class SettingsTab extends PluginSettingTab { cb.setClass('add-exclude-folder'); cb.setTooltip('Add excluded folder'); cb.onClick(() => { - const excludedFolder = new ExcludedFolder('', true, true, true, false, this.plugin.settings.excludeFolders.length); + const excludedFolder = new ExcludedFolder('', this.plugin.settings.excludeFolders.length); this.addExcludeFolderListItem(containerEl, excludedFolder); this.addExcludedFolder(excludedFolder); this.display(); @@ -120,6 +138,8 @@ export class SettingsTab extends PluginSettingTab { cb.inputEl, this.plugin ); + // @ts-ignore + cb.containerEl.addClass('fn-exclude-folder-path'); cb.setPlaceholder('Folder path'); cb.setValue(excludedFolder.path); cb.onChange((value) => { @@ -198,14 +218,15 @@ export class ExcludedFolder { disableSync: boolean; disableAutoCreate: boolean; disableFolderNote: boolean; - enableCollapsing: boolean; + enableCollappsing: boolean; position: number; - constructor(path: string, subFolders: boolean, disableSync: boolean, disableAutoCreate: boolean, disableFolderNote: boolean, position: number) { + constructor(path: string, position: number) { this.path = path; - this.subFolders = subFolders; - this.disableSync = disableSync; - this.disableAutoCreate = disableAutoCreate; - this.disableFolderNote = disableFolderNote; + this.subFolders = true; + this.disableSync = true; + this.disableAutoCreate = true; + this.disableFolderNote = false; + this.enableCollappsing = false; this.position = position; } } \ No newline at end of file diff --git a/src/suggesters/templateSuggester.ts b/src/suggesters/templateSuggester.ts new file mode 100644 index 0000000..e39a9f7 --- /dev/null +++ b/src/suggesters/templateSuggester.ts @@ -0,0 +1,70 @@ +// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater + +import { TAbstractFile, TFile, TFolder, Vault } from "obsidian"; +import { TextInputSuggest } from "./suggest"; +import FolderNotesPlugin from "../main"; +import { getTemplatePlugins } from "src/template"; +export enum FileSuggestMode { + TemplateFiles, + ScriptFiles, +} + +export class TemplateSuggest extends TextInputSuggest { + constructor( + public inputEl: HTMLInputElement, + private plugin: FolderNotesPlugin + ) { + super(inputEl); + } + + + get_error_msg(mode: FileSuggestMode): string { + switch (mode) { + case FileSuggestMode.TemplateFiles: + return `Templates folder doesn't exist`; + case FileSuggestMode.ScriptFiles: + return `User Scripts folder doesn't exist`; + } + } + + getSuggestions(input_str: string): TFile[] { + const { templateFolder, templaterPlugin } = getTemplatePlugins(this.plugin.app); + if ((!templateFolder || templateFolder?.trim() === "") && !templaterPlugin) { + this.plugin.settings.templatePath = ""; + this.plugin.saveSettings(); + return []; + } + let folder: TFolder; + if (templaterPlugin) { + folder = this.plugin.app.vault.getAbstractFileByPath(templaterPlugin.plugin?.settings?.templates_folder as string) as TFolder; + + } else { + folder = this.plugin.app.vault.getAbstractFileByPath(templateFolder) as TFolder; + } + + const files: TFile[] = []; + const lower_input_str = input_str.toLowerCase(); + + Vault.recurseChildren(folder, (file: TAbstractFile) => { + if (file instanceof TFile && + file.path.toLowerCase().contains(lower_input_str) + ) { + files.push(file); + } + }); + + return files; + } + + renderSuggestion(file: TFile, el: HTMLElement): void { + el.setText(file.name.replace(".md", "")); + } + + selectSuggestion(file: TFile): void { + this.inputEl.value = file.name.replace(".md", ""); + this.inputEl.trigger("input"); + this.plugin.settings.templatePath = file.path; + this.plugin.saveSettings(); + this.close(); + } +} \ No newline at end of file diff --git a/src/template.ts b/src/template.ts new file mode 100644 index 0000000..cec1b61 --- /dev/null +++ b/src/template.ts @@ -0,0 +1,92 @@ +// Thanks to @mgmeyers for the creating the obsidian kanban plugin https://github.com/mgmeyers/obsidian-kanban +// from where I got the template code for this plugin +// https://github.com/mgmeyers/obsidian-kanban/blob/48e6c278ce9140b7e034b181432321f697d6e45e/src/components/helpers.ts + +import { TFile, MarkdownView, App } from 'obsidian'; +import FolderNotesPlugin from './main'; +export async function applyTemplate( + plugin: FolderNotesPlugin, + templatePath?: string +) { + const templateFile = templatePath + ? plugin.app.vault.getAbstractFileByPath(templatePath) + : null; + + if (templateFile && templateFile instanceof TFile) { + const activeView = app.workspace.getActiveViewOfType(MarkdownView); + + try { + // Force the view to source mode, if needed + if (activeView?.getMode() !== 'source') { + await activeView?.setState( + { + ...activeView.getState(), + mode: 'source', + }, + {} + ); + } + + const { + templatesEnabled, + templaterEnabled, + templatesPlugin, + templaterPlugin, + } = getTemplatePlugins(plugin.app); + + const templateContent = await plugin.app.vault.read(templateFile); + + // If both plugins are enabled, attempt to detect templater first + if (templatesEnabled && templaterEnabled) { + if (/<%/.test(templateContent)) { + return await templaterPlugin.append_template_to_active_file( + templateFile + ); + } + + return await templatesPlugin.instance.insertTemplate(templateFile); + } + + if (templatesEnabled) { + return await templatesPlugin.instance.insertTemplate(templateFile); + } + + if (templaterEnabled) { + return await templaterPlugin.append_template_to_active_file( + templateFile + ); + } + + } catch (e) { + console.error(e); + } + } +} + +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' + ); + const templaterEmptyFileTemplate = + templaterPlugin && + (this.app as any).plugins.plugins['templater-obsidian'].settings + ?.empty_file_template; + + const templateFolder = templatesEnabled + ? templatesPlugin.instance.options.folder + : templaterPlugin + ? templaterPlugin.settings.template_folder + : undefined; + + return { + templatesPlugin, + templatesEnabled, + templaterPlugin: templaterPlugin?.templater, + templaterEnabled, + templaterEmptyFileTemplate, + templateFolder, + }; +} \ No newline at end of file diff --git a/styles.css b/styles.css index 765519e..5f703b7 100644 --- a/styles.css +++ b/styles.css @@ -17,17 +17,24 @@ } .fn-exclude-folder-list-item { + display: flex; + align-items: center; + padding: 0.75rem 0; border-top: none; - float: left; - display: block; + padding-top: 0; } -.fn-exclude-folder-list-item input { - width: 34.5rem; +.fn-exclude-folder-path { + width: calc(100% - 20px); } -@media screen and (max-width: 1250px) { - .fn-exclude-folder-list-item input { - width: 100%; - } +.fn-exclude-folder-list-item .setting-item-control { + width: 100%; + justify-content: flex-end; + flex: 1 1 auto; + display: flex; +} + +.fn-exclude-folder-list-item > *.last-child { + margin-right: 0; } \ No newline at end of file From e9380e58735911949452952b39b10ac261e5aa4d Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Sun, 19 Mar 2023 13:35:04 +0100 Subject: [PATCH 7/7] Settings progress --- src/main.ts | 95 ++++++++++-------------------- src/modals/confirmCreation.ts | 42 +++++++++++++ src/modals/exludeFolderSettings.ts | 4 +- src/settings.ts | 33 ++++++++++- styles.css | 9 +++ 5 files changed, 115 insertions(+), 68 deletions(-) create mode 100644 src/modals/confirmCreation.ts diff --git a/src/main.ts b/src/main.ts index fb53894..3755bc0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -24,9 +24,8 @@ export default class FolderNotesPlugin extends Plugin { if (!(folder instanceof TFolder)) return; const excludedFolder = this.settings.excludeFolders.find( - (excludedFolder) => (excludedFolder.path === - folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length)) || - (excludedFolder.path === folder?.path.slice(0, folder.path?.lastIndexOf("/")).slice(0, folder.path?.lastIndexOf("/")) + (excludedFolder) => (excludedFolder.path === folder.path) || + (excludedFolder.path === folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length) && excludedFolder.subFolders)); if (excludedFolder?.disableAutoCreate) return; @@ -34,7 +33,7 @@ export default class FolderNotesPlugin extends Plugin { if (!path) return; const file = this.app.vault.getAbstractFileByPath(path); if (file) return; - this.createFolderNote(path, true); + this.createFolderNote(path, true, true); })); @@ -42,6 +41,12 @@ export default class FolderNotesPlugin extends Plugin { if (!this.settings.syncFolderName) return; if (file instanceof TFolder) { const folder = this.app.vault.getAbstractFileByPath(file?.path); + if (!folder) return; + const excludedFolder = this.settings.excludeFolders.find( + (excludedFolder) => (excludedFolder.path === folder.path) || + (excludedFolder.path === folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length) + && excludedFolder.subFolders)); + if (excludedFolder?.disableSync) return; const oldName = oldPath.substring(oldPath.lastIndexOf('/' || '\\')); const newPath = folder?.path + '/' + folder?.name + '.md'; if (folder instanceof TFolder) { @@ -54,7 +59,11 @@ export default class FolderNotesPlugin extends Plugin { } } else if (file instanceof TFile) { const folder = this.app.vault.getAbstractFileByPath(oldPath.substring(0, oldPath.lastIndexOf('/' || '\\'))); - const excludedFolder = this.settings.excludeFolders.find((excludedFolder) => excludedFolder.path === folder?.path); + if (!folder) return; + const excludedFolder = this.settings.excludeFolders.find( + (excludedFolder) => (excludedFolder.path === folder.path) || + (excludedFolder.path === folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length) + && excludedFolder.subFolders)); if (excludedFolder?.disableSync) return; if (file.name !== folder?.name + '.md') return; if (folder instanceof TFolder) { @@ -68,6 +77,7 @@ export default class FolderNotesPlugin extends Plugin { if (rec.type === 'childList') { (rec.target).querySelectorAll('div.nav-folder-title-content') .forEach((element: HTMLElement) => { + if (element.onclick) return; element.onclick = (event: MouseEvent) => this.handleFolderClick(event); }); } @@ -88,22 +98,24 @@ export default class FolderNotesPlugin extends Plugin { return; } - const folder = event.target.parentElement?.getAttribute('data-path'); const excludedFolder = this.settings.excludeFolders.find( - (excludedFolder) => (excludedFolder.path === folder?.slice(0, folder?.lastIndexOf("/") >= 0 ? folder?.lastIndexOf("/") : folder.length)) || - (excludedFolder.path === folder?.slice(0, folder?.lastIndexOf("/")).slice(0, folder?.lastIndexOf("/")) + (excludedFolder) => (excludedFolder.path === folder) || + (excludedFolder.path === folder?.slice(0, folder?.lastIndexOf("/") >= 0 ? folder?.lastIndexOf("/") : folder.length) && excludedFolder.subFolders)); - if (excludedFolder?.enableCollappsing && excludedFolder?.disableFolderNote) { + if (excludedFolder?.disableFolderNote) { event.target.onclick = null; event.target.click(); + event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file') + .forEach((element: HTMLElement) => { + if (element.innerText === (event.target as HTMLElement)?.innerText && element.classList.contains('is-folder-note')) { + element.classList.remove('is-folder-note'); + } + }); return; - } else if (excludedFolder?.enableCollappsing) { + } else if (excludedFolder?.enableCollapsing || this.settings.enableCollapsing) { event.target.onclick = null; event.target.click(); - event.target.onclick = (event: MouseEvent) => this.handFolderClickWithCollapse(event); - event.target.click(); - return; } const path = folder + '/' + event.target.innerText + '.md'; @@ -113,13 +125,14 @@ export default class FolderNotesPlugin extends Plugin { event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file') .forEach((element: HTMLElement) => { if (element.innerText === (event.target as HTMLElement)?.innerText && !element.classList.contains('is-folder-note')) { + console.log(element) element.classList.add('is-folder-note'); } }); } else if (event.altKey || event.ctrlKey) { if ((this.settings.altKey && event.altKey) || (this.settings.ctrlKey && event.ctrlKey)) { - this.createFolderNote(path); + this.createFolderNote(path, true, true); if (!this.settings.hideFolderNote) return; event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file') .forEach((element: HTMLElement) => { @@ -137,58 +150,12 @@ export default class FolderNotesPlugin extends Plugin { } } - handFolderClickWithCollapse(event: MouseEvent) { - console.log(event) - if (!(event.target instanceof HTMLElement)) return; - if (!document.body.classList.contains('folder-notes-plugin')) { - event.target.onclick = null; - event.target.click(); - return; - } - console.log('handFolderClickWithCollapse') - - const folder = event.target.parentElement?.getAttribute('data-path'); - const path = folder + '/' + event.target.innerText + '.md'; - console.log(path) - - - if (this.app.vault.getAbstractFileByPath(path)) { - console.log('openFolderNote') - this.openFolderNote(path); - if (!this.settings.hideFolderNote) return; - event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file') - .forEach((element: HTMLElement) => { - if (element.innerText === (event.target as HTMLElement)?.innerText && !element.classList.contains('is-folder-note')) { - element.classList.add('is-folder-note'); - } - }); - - } else if (event.altKey || event.ctrlKey) { - console.log(event.altKey, event.ctrlKey); - if ((this.settings.altKey && event.altKey) || (this.settings.ctrlKey && event.ctrlKey)) { - this.createFolderNote(path); - if (!this.settings.hideFolderNote) return; - event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file') - .forEach((element: HTMLElement) => { - if (element.innerText === (event.target as HTMLElement)?.innerText && !element.classList.contains('is-folder-note')) { - element.classList.add('is-folder-note'); - } - }); - } else { - event.target.onclick = null; - event.target.click(); - } - } else { - console.log('click') - event.target.onclick = null; - event.target.click(); - } - } - - async createFolderNote(path: string, useModal?: boolean) { + async createFolderNote(path: string, openFile: boolean, useModal?: boolean) { const leaf = this.app.workspace.getLeaf(false); const file = await this.app.vault.create(path, ''); - await leaf.openFile(file); + if (openFile) { + await leaf.openFile(file); + } applyTemplate(this, this.settings.templatePath); if (!this.settings.autoCreate) return; if (!useModal) return; diff --git a/src/modals/confirmCreation.ts b/src/modals/confirmCreation.ts new file mode 100644 index 0000000..9bc97d0 --- /dev/null +++ b/src/modals/confirmCreation.ts @@ -0,0 +1,42 @@ +import { App, Modal, Setting, TFolder } from 'obsidian'; +import FolderNotesPlugin from '../main'; +export default class ConfirmationModal extends Modal { + plugin: FolderNotesPlugin; + app: App; + folder: TFolder; + constructor(app: App, plugin: FolderNotesPlugin) { + super(app); + this.plugin = plugin; + this.app = app; + } + onOpen() { + const { contentEl } = this; + contentEl.createEl('h2', { text: 'Create folder note for every folder' }); + const setting = new Setting(contentEl) + setting.infoEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).style.color = '#fb464c'; + setting.infoEl.createEl('p', { text: 'This feature will create a folder note for every folder in your vault.' }); + setting.infoEl.createEl('p', { text: 'Every folder that already has a folder note will be ignored' }); + setting.infoEl.parentElement?.classList.add('fn-confirmation-modal') + const button = setting.infoEl.createEl('button', { text: 'Create' }); + button.classList.add('mod-warning', 'fn-confirmation-modal-button'); + button.addEventListener('click', async () => { + this.close(); + this.app.vault.getAllLoadedFiles().forEach(async (file) => { + if (file instanceof TFolder) { + if (this.app.vault.getAbstractFileByPath(file.path + '/' + file.name + '.md')) return; + await this.plugin.createFolderNote(file.path + '/' + file.name + '.md', false); + } + }) + }); + // focus on the button + button.focus(); + const cancelButton = setting.infoEl.createEl('button', { text: 'Cancel' }); + cancelButton.addEventListener('click', async () => { + this.close(); + }); + } + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +} \ No newline at end of file diff --git a/src/modals/exludeFolderSettings.ts b/src/modals/exludeFolderSettings.ts index 39b3287..47df07c 100644 --- a/src/modals/exludeFolderSettings.ts +++ b/src/modals/exludeFolderSettings.ts @@ -74,9 +74,9 @@ export default class ExcludedFolderSettings extends Modal { .setDesc('Choose if the folder should be collapsed when the folder note is opened') .addToggle((toggle) => toggle - .setValue(this.excludedFolder.enableCollappsing) + .setValue(this.excludedFolder.enableCollapsing) .onChange(async (value) => { - this.excludedFolder.enableCollappsing = value; + this.excludedFolder.enableCollapsing = value; await this.plugin.saveSettings(); }) ); diff --git a/src/settings.ts b/src/settings.ts index 396e429..08f2566 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -3,6 +3,7 @@ import FolderNotesPlugin from "./main"; import { FolderSuggest } from "./suggesters/folderSuggester"; import ExcludedFolderSettings from "./modals/exludeFolderSettings"; import { TemplateSuggest } from "./suggesters/templateSuggester"; +import ConfirmationModal from "./modals/confirmCreation"; export interface FolderNotesSettings { syncFolderName: boolean; ctrlKey: boolean; @@ -10,6 +11,7 @@ export interface FolderNotesSettings { hideFolderNote: boolean; templatePath: string; autoCreate: boolean; + enableCollapsing: boolean; excludeFolders: ExcludedFolder[]; } @@ -20,6 +22,7 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = { hideFolderNote: true, templatePath: '', autoCreate: false, + enableCollapsing: false, excludeFolders: [], }; export class SettingsTab extends PluginSettingTab { @@ -36,6 +39,18 @@ export class SettingsTab extends PluginSettingTab { containerEl.createEl('h2', { text: 'Folder notes settings' }); + new Setting(containerEl) + .setName('Disable folder collapsing') + .setDesc('Disable the ability to collapse folders by clicking on the folder name') + .addToggle((toggle) => + toggle + .setValue(!this.plugin.settings.enableCollapsing) + .onChange(async (value) => { + this.plugin.settings.enableCollapsing = !value; + await this.plugin.saveSettings(); + }) + ); + new Setting(containerEl) .setName('Hide folder note') .setDesc('Hide the folder note in the file explorer') @@ -110,6 +125,20 @@ export class SettingsTab extends PluginSettingTab { }); }); + new Setting(containerEl) + .setName('Create folder note for every folder') + .setDesc('Create a folder note for every folder in the vault') + .addButton((cb) => { + cb.setIcon('plus'); + + cb.setTooltip('Create folder notes'); + cb.onClick(async () => { + new ConfirmationModal(this.app, this.plugin).open(); + }); + }); + + + new Setting(containerEl) .setHeading() .setName('Manage excluded folders') @@ -218,7 +247,7 @@ export class ExcludedFolder { disableSync: boolean; disableAutoCreate: boolean; disableFolderNote: boolean; - enableCollappsing: boolean; + enableCollapsing: boolean; position: number; constructor(path: string, position: number) { this.path = path; @@ -226,7 +255,7 @@ export class ExcludedFolder { this.disableSync = true; this.disableAutoCreate = true; this.disableFolderNote = false; - this.enableCollappsing = false; + this.enableCollapsing = false; this.position = position; } } \ No newline at end of file diff --git a/styles.css b/styles.css index 5f703b7..2e82e6b 100644 --- a/styles.css +++ b/styles.css @@ -12,6 +12,7 @@ display: none; } + .nav-folder-collapse-indicator:hover { cursor: pointer; } @@ -37,4 +38,12 @@ .fn-exclude-folder-list-item > *.last-child { margin-right: 0; +} + +.fn-confirmation-modal { + padding-bottom: 0; +} + +.fn-confirmation-modal-button { + margin-right: 0.7rem; } \ No newline at end of file