mirror of
https://github.com/lostpaul/obsidian-folder-notes.git
synced 2026-07-22 07:40:24 +00:00
Fix eslint issues 1/2
This commit is contained in:
parent
2683ee1a1a
commit
1e99850592
38 changed files with 5759 additions and 648 deletions
|
|
@ -31,7 +31,6 @@ esbuild.build({
|
|||
'@lezer/common',
|
||||
'@lezer/highlight',
|
||||
'@lezer/lr',
|
||||
"f:/Obsidian/test/.obsidian/plugins/obsidian-folder-notes/node_modules/obsidian",
|
||||
...builtins],
|
||||
format: 'cjs',
|
||||
watch: !prod,
|
||||
|
|
|
|||
|
|
@ -1,17 +1,61 @@
|
|||
import tseslint from "typescript-eslint";
|
||||
import obsidianmd from "eslint-plugin-obsidianmd";
|
||||
import json from "@eslint/json";
|
||||
|
||||
export default [
|
||||
...obsidianmd.configs.recommended,
|
||||
{
|
||||
files: ["manifest.json"],
|
||||
language: "json/json",
|
||||
plugins: {
|
||||
json
|
||||
},
|
||||
rules: {
|
||||
"no-irregular-whitespace": "off",
|
||||
"obsidianmd/no-plugin-as-component": "off",
|
||||
"obsidianmd/no-view-references-in-plugin": "off",
|
||||
"obsidianmd/no-unsupported-api": "off",
|
||||
"obsidianmd/prefer-file-manager-trash-file": "off",
|
||||
"obsidianmd/prefer-instanceof": "off",
|
||||
"obsidianmd/validate-manifest": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["package.json"],
|
||||
rules: {
|
||||
"no-irregular-whitespace": "off",
|
||||
"depend/ban-dependencies": "off",
|
||||
"obsidianmd/no-plugin-as-component": "off",
|
||||
"obsidianmd/no-view-references-in-plugin": "off",
|
||||
"obsidianmd/no-unsupported-api": "off",
|
||||
"obsidianmd/prefer-file-manager-trash-file": "off",
|
||||
"obsidianmd/prefer-instanceof": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/*.{js,mjs,cjs}"],
|
||||
...tseslint.configs.disableTypeChecked,
|
||||
rules: {
|
||||
...tseslint.configs.disableTypeChecked.rules,
|
||||
"obsidianmd/no-plugin-as-component": "off",
|
||||
"obsidianmd/no-view-references-in-plugin": "off",
|
||||
"obsidianmd/no-unsupported-api": "off",
|
||||
"obsidianmd/prefer-file-manager-trash-file": "off",
|
||||
"obsidianmd/prefer-instanceof": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/*.ts"],
|
||||
languageOptions: {
|
||||
parser: tseslint.parser,
|
||||
parserOptions: {
|
||||
sourceType: "module"
|
||||
sourceType: "module",
|
||||
project: "./tsconfig.json"
|
||||
}
|
||||
},
|
||||
ignores: [
|
||||
"**/node_modules/**",
|
||||
"**/dist/**",
|
||||
"**/dist/**"
|
||||
],
|
||||
plugins: {
|
||||
"@typescript-eslint": tseslint.plugin
|
||||
|
|
@ -143,7 +187,7 @@ export default [
|
|||
],
|
||||
'max-len': [
|
||||
'warn', {
|
||||
code: 100,
|
||||
code: 110,
|
||||
ignoreComments: true,
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"id": "folder-notes",
|
||||
"name": "Folder notes",
|
||||
"version": "1.8.19",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.",
|
||||
"author": "Lost Paul",
|
||||
"authorUrl": "https://github.com/LostPaul",
|
||||
"fundingUrl": "https://ko-fi.com/paul305844",
|
||||
"helpUrl": "https://lostpaul.github.io/obsidian-folder-notes/",
|
||||
"isDesktopOnly": false
|
||||
"id": "folder-notes",
|
||||
"name": "Folder notes",
|
||||
"version": "1.8.21",
|
||||
"minAppVersion": "1.4.10",
|
||||
"description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.",
|
||||
"author": "Lost Paul",
|
||||
"authorUrl": "https://github.com/LostPaul",
|
||||
"fundingUrl": "https://ko-fi.com/paul305844",
|
||||
"helpUrl": "https://lostpaul.github.io/obsidian-folder-notes/",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
5500
package-lock.json
generated
5500
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -23,6 +23,7 @@
|
|||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.14.47",
|
||||
"eslint": "^9.32.0",
|
||||
"eslint-plugin-obsidianmd": "^0.3.0",
|
||||
"front-matter-plugin-api-provider": "^0.1.4-alpha",
|
||||
"globals": "^16.3.0",
|
||||
"jiti": "^2.5.1",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
type TAbstractFile,
|
||||
type Editor,
|
||||
type MarkdownView,
|
||||
type MarkdownFileInfo,
|
||||
} from 'obsidian';
|
||||
import type FolderNotesPlugin from './main';
|
||||
import {
|
||||
|
|
@ -31,6 +32,7 @@ import {
|
|||
showFolderNoteInFileExplorer,
|
||||
} from './functions/styleFunctions';
|
||||
|
||||
type MarkdownEditorContext = MarkdownView | MarkdownFileInfo;
|
||||
|
||||
|
||||
export class Commands {
|
||||
|
|
@ -60,7 +62,7 @@ export class Commands {
|
|||
const folderNote = getFolderNote(this.plugin, folder.path);
|
||||
if (folderNote instanceof TFile && folderNote === file) return false;
|
||||
if (checking) return true;
|
||||
turnIntoFolderNote(this.plugin, file, folder, folderNote);
|
||||
void turnIntoFolderNote(this.plugin, file, folder, folderNote);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -80,19 +82,19 @@ export class Commands {
|
|||
const automaticallyCreateFolderNote =
|
||||
this.plugin.settings.autoCreate;
|
||||
this.plugin.settings.autoCreate = false;
|
||||
this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
await this.plugin.app.vault.createFolder(newPath);
|
||||
const folder = this.plugin.app.vault.getAbstractFileByPath(newPath);
|
||||
if (!(folder instanceof TFolder)) return;
|
||||
createFolderNote(this.plugin, folder.path, true, '.' + file.extension, false, file);
|
||||
await createFolderNote(this.plugin, folder.path, true, '.' + file.extension, false, file);
|
||||
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
|
||||
this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
},
|
||||
});
|
||||
|
||||
this.plugin.addCommand({
|
||||
id: 'create-folder-note-for-current-folder',
|
||||
name: 'Create markdown folder note for this folder',
|
||||
name: 'Create Markdown folder note for this folder',
|
||||
checkCallback: (checking) => {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
if (!(file instanceof TFile)) return false;
|
||||
|
|
@ -100,7 +102,7 @@ export class Commands {
|
|||
if (!(folder instanceof TFolder)) return false;
|
||||
if (folder.path === '' || folder.path === '/') return false;
|
||||
if (checking) return true;
|
||||
createFolderNote(this.plugin, folder.path, true, '.md', false);
|
||||
void createFolderNote(this.plugin, folder.path, true, '.md', false);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -116,7 +118,7 @@ export class Commands {
|
|||
if (!(folder instanceof TFolder)) return false;
|
||||
if (folder.path === '' || folder.path === '/') return false;
|
||||
if (checking) return true;
|
||||
createFolderNote(this.plugin, folder.path, true, '.' + fileType, false);
|
||||
void createFolderNote(this.plugin, folder.path, true, '.' + fileType, false);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
@ -136,7 +138,7 @@ export class Commands {
|
|||
// Everything is fine and not checking, let's create the folder note.
|
||||
const ext = '.' + fileType;
|
||||
const { path } = folder;
|
||||
createFolderNote(this.plugin, path, true, ext, false);
|
||||
void createFolderNote(this.plugin, path, true, ext, false);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
@ -152,7 +154,7 @@ export class Commands {
|
|||
const folderNote = getFolderNote(this.plugin, folder.path);
|
||||
if (!(folderNote instanceof TFile)) return false;
|
||||
if (checking) return true;
|
||||
deleteFolderNote(this.plugin, folderNote, true);
|
||||
void deleteFolderNote(this.plugin, folderNote, true);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -168,7 +170,7 @@ export class Commands {
|
|||
if (checking) return true;
|
||||
|
||||
// Everything is fine and not checking, let's delete the folder note.
|
||||
deleteFolderNote(this.plugin, folderNote, true);
|
||||
void deleteFolderNote(this.plugin, folderNote, true);
|
||||
},
|
||||
});
|
||||
this.plugin.addCommand({
|
||||
|
|
@ -182,7 +184,7 @@ export class Commands {
|
|||
const folderNote = getFolderNote(this.plugin, folder.path);
|
||||
if (!(folderNote instanceof TFile)) return false;
|
||||
if (checking) return true;
|
||||
openFolderNote(this.plugin, folderNote);
|
||||
void openFolderNote(this.plugin, folderNote);
|
||||
},
|
||||
});
|
||||
this.plugin.addCommand({
|
||||
|
|
@ -197,14 +199,14 @@ export class Commands {
|
|||
if (checking) return true;
|
||||
|
||||
// Everything is fine and not checking, let's open the folder note.
|
||||
openFolderNote(this.plugin, folderNote);
|
||||
void openFolderNote(this.plugin, folderNote);
|
||||
},
|
||||
});
|
||||
|
||||
this.plugin.addCommand({
|
||||
id: 'create-folder-note-from-selected-text',
|
||||
name: 'Create folder note from selection',
|
||||
editorCheckCallback: (checking: boolean, editor: Editor, view: MarkdownView) => {
|
||||
editorCheckCallback: (checking: boolean, editor: Editor, view: MarkdownEditorContext) => {
|
||||
const text = editor.getSelection().trim();
|
||||
const { file } = view;
|
||||
if (!(file instanceof TFile)) return false;
|
||||
|
|
@ -230,8 +232,8 @@ export class Commands {
|
|||
new Notice('Folder note already exists');
|
||||
return false;
|
||||
}
|
||||
this.plugin.app.vault.createFolder(text);
|
||||
createFolderNote(this.plugin, text, false);
|
||||
void this.plugin.app.vault.createFolder(text);
|
||||
void createFolderNote(this.plugin, text, false);
|
||||
|
||||
} else {
|
||||
const folderFullPath = folderPath + '/' + text;
|
||||
|
|
@ -250,8 +252,8 @@ export class Commands {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
this.plugin.app.vault.createFolder(folderPath + '/' + text);
|
||||
createFolderNote(this.plugin, folderPath + '/' + text, false);
|
||||
void this.plugin.app.vault.createFolder(folderPath + '/' + text);
|
||||
void createFolderNote(this.plugin, folderPath + '/' + text, false);
|
||||
}
|
||||
|
||||
const { folderNoteName } = this.plugin.settings;
|
||||
|
|
@ -317,7 +319,7 @@ export class Commands {
|
|||
const automaticallyCreateFolderNote =
|
||||
this.plugin.settings.autoCreate;
|
||||
this.plugin.settings.autoCreate = false;
|
||||
this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
await this.plugin.app.vault.createFolder(newPath);
|
||||
const newFolder = this.plugin.app.vault
|
||||
.getAbstractFileByPath(newPath);
|
||||
|
|
@ -331,7 +333,7 @@ export class Commands {
|
|||
file,
|
||||
);
|
||||
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
|
||||
this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -347,7 +349,7 @@ export class Commands {
|
|||
item.onClick(() => {
|
||||
if (!folder || !(folder instanceof TFolder)) return;
|
||||
const folderNote = getFolderNote(this.plugin, folder.path);
|
||||
turnIntoFolderNote(this.plugin, file, folder, folderNote);
|
||||
void turnIntoFolderNote(this.plugin, file, folder, folderNote);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -380,7 +382,7 @@ export class Commands {
|
|||
(excluded) =>
|
||||
(excluded.path !== file.path) || excluded.detached,
|
||||
);
|
||||
this.plugin.saveSettings(true);
|
||||
void this.plugin.saveSettings(true);
|
||||
new Notice('Successfully removed folder from excluded folders');
|
||||
});
|
||||
});
|
||||
|
|
@ -393,7 +395,7 @@ export class Commands {
|
|||
item.setTitle('Remove folder from detached folders');
|
||||
item.setIcon('trash');
|
||||
item.onClick(() => {
|
||||
deleteExcludedFolder(this.plugin, detachedExcludedFolder);
|
||||
void deleteExcludedFolder(this.plugin, detachedExcludedFolder);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -411,7 +413,7 @@ export class Commands {
|
|||
this.plugin,
|
||||
);
|
||||
this.plugin.settings.excludeFolders.push(newExcludedFolder);
|
||||
this.plugin.saveSettings(true);
|
||||
void this.plugin.saveSettings(true);
|
||||
new Notice('Successfully excluded folder from folder notes');
|
||||
});
|
||||
});
|
||||
|
|
@ -425,7 +427,7 @@ export class Commands {
|
|||
item.setTitle('Delete folder note');
|
||||
item.setIcon('trash');
|
||||
item.onClick(() => {
|
||||
deleteFolderNote(this.plugin, folderNote, true);
|
||||
void deleteFolderNote(this.plugin, folderNote, true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -433,7 +435,7 @@ export class Commands {
|
|||
item.setTitle('Open folder note');
|
||||
item.setIcon('chevron-right-square');
|
||||
item.onClick(() => {
|
||||
openFolderNote(this.plugin, folderNote);
|
||||
void openFolderNote(this.plugin, folderNote);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -474,10 +476,10 @@ export class Commands {
|
|||
}
|
||||
} else {
|
||||
folderMenu.addItem((item) => {
|
||||
item.setTitle('Create markdown folder note');
|
||||
item.setTitle('Create Markdown folder note');
|
||||
item.setIcon('edit');
|
||||
item.onClick(() => {
|
||||
createFolderNote(this.plugin, file.path, true, '.md');
|
||||
void createFolderNote(this.plugin, file.path, true, '.md');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -487,7 +489,7 @@ export class Commands {
|
|||
item.setTitle(`Create ${fileType} folder note`);
|
||||
item.setIcon('edit');
|
||||
item.onClick(() => {
|
||||
createFolderNote(this.plugin, file.path, true, '.' + fileType);
|
||||
void createFolderNote(this.plugin, file.path, true, '.' + fileType);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -500,8 +502,8 @@ export class Commands {
|
|||
this.plugin.settings.useSubmenus
|
||||
) {
|
||||
menu.addItem(async (item) => {
|
||||
item.setTitle('Folder Note Commands').setIcon('folder-edit');
|
||||
let subMenu: Menu = item.setSubmenu() as Menu;
|
||||
item.setTitle('Folder note commands').setIcon('folder-edit');
|
||||
let subMenu: Menu = item.setSubmenu();
|
||||
addFolderNoteActions(subMenu);
|
||||
});
|
||||
} else {
|
||||
|
|
@ -512,7 +514,7 @@ export class Commands {
|
|||
|
||||
editorCommands(): void {
|
||||
// eslint-disable-next-line max-len
|
||||
this.plugin.registerEvent(this.plugin.app.workspace.on('editor-menu', (menu: Menu, editor: Editor, view: MarkdownView) => {
|
||||
this.plugin.registerEvent(this.plugin.app.workspace.on('editor-menu', (menu: Menu, editor: Editor, view: MarkdownEditorContext) => {
|
||||
const text = editor.getSelection().trim();
|
||||
if (!text || text.trim() === '') return;
|
||||
menu.addItem((item) => {
|
||||
|
|
@ -543,8 +545,8 @@ export class Commands {
|
|||
if (folder instanceof TFolder) {
|
||||
return new Notice('Folder note already exists');
|
||||
}
|
||||
this.plugin.app.vault.createFolder(text);
|
||||
createFolderNote(this.plugin, text, false);
|
||||
void this.plugin.app.vault.createFolder(text);
|
||||
void createFolderNote(this.plugin, text, false);
|
||||
|
||||
} else {
|
||||
folder = this.plugin.app.vault.getAbstractFileByPath(
|
||||
|
|
@ -565,8 +567,8 @@ export class Commands {
|
|||
return new Notice('File already exists');
|
||||
}
|
||||
}
|
||||
this.plugin.app.vault.createFolder(folderPath + '/' + text);
|
||||
createFolderNote(this.plugin, folderPath + '/' + text, false);
|
||||
void this.plugin.app.vault.createFolder(folderPath + '/' + text);
|
||||
void createFolderNote(this.plugin, folderPath + '/' + text, false);
|
||||
}
|
||||
if (fileName !== text) {
|
||||
editor.replaceSelection(`[[${fileName}]]`);
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ function aggregateFlags(
|
|||
for (const property of propertiesToCopy) {
|
||||
const value = (matchedFolder as Partial<ExcludedFolder>)[property];
|
||||
if (value === true) {
|
||||
(result as Partial<ExcludedFolder>)[property] = true as never;
|
||||
(result)[property] = true as never;
|
||||
} else if (!value) {
|
||||
(result as Partial<ExcludedFolder>)[property] = false as never;
|
||||
(result)[property] = false as never;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ export function getExcludedFolder(
|
|||
const whitelist = getWhitelistedFolder(
|
||||
plugin,
|
||||
path,
|
||||
) as WhitelistedFolder | WhitelistedPattern | undefined;
|
||||
);
|
||||
|
||||
let skipWhitelist = ignoreWhitelist ?? false;
|
||||
if (excluded?.detached) skipWhitelist = true;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export default class PatternSettings extends Modal {
|
|||
|
||||
new Setting(contentEl)
|
||||
.setName('Disable folder name sync')
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
.setDesc('Choose if the folder name should be renamed when the file name has been changed')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default class WhitelistFolderSettings extends Modal {
|
|||
|
||||
new Setting(contentEl)
|
||||
.setName('Enable folder name sync')
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
.setDesc('Choose if the name of a folder note should be renamed when the folder name is changed')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default class WhitelistPatternSettings extends Modal {
|
|||
contentEl.createEl('h2', { text: 'Whitelisted pattern settings' });
|
||||
new Setting(contentEl)
|
||||
.setName('Enable folder name sync')
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
.setDesc('Choose if the name of a folder note should be renamed when the folder name is changed')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ function initializeFolderNoteFeatures(plugin: FolderNotesPlugin): void {
|
|||
}
|
||||
|
||||
function initializeBreadcrumbs(plugin: FolderNotesPlugin): void {
|
||||
const titleContainers = document.querySelectorAll('.view-header-title-container');
|
||||
const titleContainers = activeDocument.querySelectorAll('.view-header-title-container');
|
||||
if (!titleContainers.length) return;
|
||||
titleContainers.forEach((container) => {
|
||||
if (!(container instanceof HTMLElement)) return;
|
||||
if (!(container.instanceOf(HTMLElement))) return;
|
||||
scheduleIdle(() => updateFolderNamesInPath(plugin, container), { timeout: 1000 });
|
||||
});
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ function observeFolderTitleMutations(plugin: FolderNotesPlugin): void {
|
|||
fileExplorerMutationObserver = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
for (const node of Array.from(mutation.addedNodes)) {
|
||||
if (!(node instanceof HTMLElement)) continue;
|
||||
if (!(node.instanceOf(HTMLElement))) continue;
|
||||
processAddedFolders(node, plugin);
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ function observeFolderTitleMutations(plugin: FolderNotesPlugin): void {
|
|||
}
|
||||
|
||||
function initializeAllFolderTitles(plugin: FolderNotesPlugin): void {
|
||||
const allTitles = document.querySelectorAll('.nav-folder-title-content');
|
||||
const allTitles = activeDocument.querySelectorAll('.nav-folder-title-content');
|
||||
for (const title of Array.from(allTitles)) {
|
||||
const folderTitle = title as HTMLElement;
|
||||
const folderEl = folderTitle.closest('.nav-folder-title');
|
||||
|
|
@ -97,7 +97,7 @@ function processAddedFolders(node: HTMLElement, plugin: FolderNotesPlugin): void
|
|||
const folderPath = folderEl?.getAttribute('data-path') || '';
|
||||
const RETRY_TIMEOUT = 50;
|
||||
if (!folderEl || !folderPath) {
|
||||
setTimeout(() => {
|
||||
window.setTimeout(() => {
|
||||
const retryFolderEl = folderTitle.closest('.nav-folder-title');
|
||||
const retryFolderPath = retryFolderEl?.getAttribute('data-path') || '';
|
||||
if (retryFolderEl && retryFolderPath) {
|
||||
|
|
@ -171,7 +171,7 @@ async function updateFolderNamesInPath(
|
|||
}
|
||||
// eslint-disable-next-line complexity
|
||||
titleParent?.childNodes.forEach(async (breadcrumb: HTMLElement) => {
|
||||
if (!(breadcrumb instanceof HTMLElement)) return;
|
||||
if (!(breadcrumb.instanceOf(HTMLElement))) return;
|
||||
if (breadcrumb.classList.contains('view-header-breadcrumb-separator')) {
|
||||
if (breadcrumb.nextSibling === null) {
|
||||
breadcrumb.classList.add('is-last-separator');
|
||||
|
|
@ -179,7 +179,7 @@ async function updateFolderNamesInPath(
|
|||
return;
|
||||
}
|
||||
|
||||
path += breadcrumb.getAttribute('old-name') ?? (breadcrumb as HTMLElement).innerText.trim();
|
||||
path += breadcrumb.getAttribute('old-name') ?? (breadcrumb).innerText.trim();
|
||||
path += '/';
|
||||
const folderPath = path.slice(0, -TRAILING_SLASH_LENGTH);
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ async function updateFolderNamesInPath(
|
|||
breadcrumb?.setAttribute('data-path', path.slice(0, -TRAILING_SLASH_LENGTH));
|
||||
if (!breadcrumb.onclick) {
|
||||
breadcrumb.addEventListener('click', (e) => {
|
||||
handleViewHeaderClick(e as MouseEvent, plugin);
|
||||
handleViewHeaderClick(e, plugin);
|
||||
}, { capture: true });
|
||||
}
|
||||
|
||||
|
|
@ -230,6 +230,6 @@ function scheduleIdle(callback: () => void, options?: { timeout: number }): void
|
|||
};
|
||||
windowWithIdle.requestIdleCallback(callback, options);
|
||||
} else {
|
||||
setTimeout(callback, options?.timeout || DEFAULT_IDLE_TIMEOUT);
|
||||
window.setTimeout(callback, options?.timeout || DEFAULT_IDLE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ export async function handleViewHeaderClick(
|
|||
} else if (event.altKey || Keymap.isModEvent(event) === 'tab') {
|
||||
if (await handleFolderNoteCreation(event, plugin, folderPath)) return;
|
||||
}
|
||||
(event.target as HTMLElement).onclick = null;
|
||||
(event.target as HTMLElement).click();
|
||||
(event.target).onclick = null;
|
||||
(event.target).click();
|
||||
}
|
||||
|
||||
async function isExcludedFolder(
|
||||
|
|
@ -58,7 +58,7 @@ async function handleFolderNoteReveal(plugin: FolderNotesPlugin, folderNote: TFi
|
|||
const fileExplorerPlugin = plugin.app.internalPlugins.getEnabledPluginById('file-explorer');
|
||||
if (fileExplorerPlugin && Platform.isMobile && plugin.settings.openSidebar.mobile) {
|
||||
const OPEN_SIDEBAR_DELAY = 200;
|
||||
setTimeout(() => { fileExplorerPlugin.revealInFolder(folderNote); }, OPEN_SIDEBAR_DELAY);
|
||||
window.setTimeout(() => { fileExplorerPlugin.revealInFolder(folderNote); }, OPEN_SIDEBAR_DELAY);
|
||||
} else if (fileExplorerPlugin && Platform.isDesktop && plugin.settings.openSidebar.desktop) {
|
||||
fileExplorerPlugin.revealInFolder(folderNote);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,6 @@ async function handleFolderCreation(folder: TFolder, plugin: FolderNotesPlugin):
|
|||
const folderNote = getFolderNote(plugin, folder.path);
|
||||
if (folderNote) return;
|
||||
|
||||
createFolderNote(plugin, folder.path, openFile, undefined, true);
|
||||
void createFolderNote(plugin, folder.path, openFile, undefined, true);
|
||||
addCSSClassToFileExplorerEl(folder.path, 'has-folder-note', false, plugin);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ export class ListComponent {
|
|||
emitter: CustomEventEmitter;
|
||||
containerEl: HTMLElement;
|
||||
controlEl: HTMLElement;
|
||||
emptyStateEl: HTMLElement;
|
||||
emptyStateEl!: HTMLElement;
|
||||
listEl: HTMLElement;
|
||||
values: string[];
|
||||
values!: string[];
|
||||
defaultValues: string[];
|
||||
constructor(containerEl: HTMLElement, values: string[] = [], defaultValues: string[] = []) {
|
||||
this.emitter = new CustomEventEmitter();
|
||||
|
|
@ -48,17 +48,23 @@ export class ListComponent {
|
|||
addElement(value: string): void {
|
||||
this.listEl.createSpan('setting-hotkey', (span) => {
|
||||
if (value.toLocaleLowerCase() === 'md') {
|
||||
span.innerText = 'markdown';
|
||||
const markdown = 'markdown';
|
||||
span.innerText = markdown;
|
||||
} else {
|
||||
span.innerText = value;
|
||||
}
|
||||
span.setAttribute('extension', value);
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
const removeSpan = span.createEl('span', { cls: 'ofn-list-item-remove setting-hotkey-icon' });
|
||||
// eslint-disable-next-line max-len
|
||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
|
||||
const svgElement = removeSpan.createEl('span', { cls: 'ofn-list-item-remove-icon' });
|
||||
svgElement.innerHTML = svg;
|
||||
const parser = new DOMParser();
|
||||
const svgDoc = parser.parseFromString(svg, 'image/svg+xml');
|
||||
const svgNode = svgDoc.documentElement;
|
||||
if (svgNode) {
|
||||
svgElement.appendChild(activeDocument.importNode(svgNode, true));
|
||||
}
|
||||
removeSpan.onClickEvent(() => {
|
||||
this.removeValue(value);
|
||||
span.remove();
|
||||
|
|
@ -78,7 +84,13 @@ export class ListComponent {
|
|||
const resetButton = this.controlEl.createEl('span', { cls: 'clickable-icon setting-restore-hotkey-button' });
|
||||
// eslint-disable-next-line max-len
|
||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-rotate-ccw"><path d="M3 2v6h6"></path><path d="M3 13a9 9 0 1 0 3-7.7L3 8"></path></svg>';
|
||||
resetButton.innerHTML = svg;
|
||||
const svgElement = resetButton.createEl('span', { cls: 'ofn-list-item-remove-icon' });
|
||||
const parser = new DOMParser();
|
||||
const svgDoc = parser.parseFromString(svg, 'image/svg+xml');
|
||||
const svgNode = svgDoc.documentElement;
|
||||
if (svgNode) {
|
||||
svgElement.appendChild(activeDocument.importNode(svgNode, true));
|
||||
}
|
||||
resetButton.onClickEvent(() => {
|
||||
this.setValues(this.defaultValues);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ async function handleCreateFolderNote(plugin: FolderNotesPlugin, folderNoteType:
|
|||
if (
|
||||
extension === '.excalidraw' &&
|
||||
!content.includes(
|
||||
'==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠==',
|
||||
'==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this activeDocument. ⚠==',
|
||||
)
|
||||
) {
|
||||
content = await getDefaultTemplate(plugin.app);
|
||||
|
|
@ -303,12 +303,12 @@ export async function turnIntoFolderNote(
|
|||
}
|
||||
|
||||
if (detachedExcludedFolder) {
|
||||
deleteExcludedFolder(plugin, detachedExcludedFolder);
|
||||
void deleteExcludedFolder(plugin, detachedExcludedFolder);
|
||||
}
|
||||
|
||||
await plugin.app.fileManager.renameFile(file, path);
|
||||
addCSSClassToFileExplorerEl(path, 'is-folder-note', false, plugin, true);
|
||||
addCSSClassToFileExplorerEl(folder.path, 'has-folder-note', false, plugin);
|
||||
void addCSSClassToFileExplorerEl(path, 'is-folder-note', false, plugin, true);
|
||||
void addCSSClassToFileExplorerEl(folder.path, 'has-folder-note', false, plugin);
|
||||
|
||||
removeActiveFolder(plugin);
|
||||
setActiveFolder(folder.path, plugin);
|
||||
|
|
@ -502,7 +502,7 @@ export function detachFolderNote(plugin: FolderNotesPlugin, file: TFile): void {
|
|||
excludedFolder.detached = true;
|
||||
excludedFolder.detachedFilePath = file.path;
|
||||
addExcludedFolder(plugin, excludedFolder);
|
||||
updateCSSClassesForFolderNote(file.path, plugin);
|
||||
void updateCSSClassesForFolderNote(file.path, plugin);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ export async function addCSSClassToFileExplorerEl(
|
|||
|
||||
if (!fileExplorerItem) {
|
||||
if (waitForCreate && count < MAX_RETRIES) {
|
||||
await new Promise((r) => setTimeout(r, RETRY_DELAY));
|
||||
await new Promise((r) => window.setTimeout(r, RETRY_DELAY));
|
||||
addCSSClassToFileExplorerEl(path, cssClass, parent, plugin, waitForCreate, count + 1);
|
||||
return;
|
||||
}
|
||||
|
|
@ -164,7 +164,7 @@ export async function addCSSClassToFileExplorerEl(
|
|||
}
|
||||
} else {
|
||||
fileExplorerItem.addClass(cssClass);
|
||||
document.querySelectorAll(`[data-path='${CSS.escape(path)}']`).forEach((item) => {
|
||||
activeDocument.querySelectorAll(`[data-path='${CSS.escape(path)}']`).forEach((item) => {
|
||||
item.addClass(cssClass);
|
||||
});
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ export function removeCSSClassFromFileExplorerEL(
|
|||
): void {
|
||||
if (!path) return;
|
||||
const fileExplorerItem = getFileExplorerElement(path, plugin);
|
||||
document.querySelectorAll(`[data-path='${CSS.escape(path)}']`).forEach((item) => {
|
||||
activeDocument.querySelectorAll(`[data-path='${CSS.escape(path)}']`).forEach((item) => {
|
||||
item.removeClass(cssClass);
|
||||
});
|
||||
if (!fileExplorerItem) { return; }
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ export function getFileExplorerActiveFolder(): TFolder | null {
|
|||
const activeFileOrFolder =
|
||||
fe.tree.focusedItem?.file ?? fe.activeDom?.file;
|
||||
if (!(activeFileOrFolder instanceof TFolder)) return null;
|
||||
return activeFileOrFolder as TFolder;
|
||||
return activeFileOrFolder;
|
||||
}
|
||||
|
||||
export function getFileExplorerActiveFolderNote(): TFile | null {
|
||||
|
|
|
|||
218
src/main.ts
218
src/main.ts
|
|
@ -1,5 +1,5 @@
|
|||
import {
|
||||
type TAbstractFile,
|
||||
type App, type TAbstractFile,
|
||||
type MarkdownPostProcessorContext,
|
||||
type WorkspaceLeaf,
|
||||
Plugin, TFile, TFolder,
|
||||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import {
|
||||
type FolderNotesSettings, DEFAULT_SETTINGS, SettingsTab,
|
||||
} from './settings/SettingsTab';
|
||||
import { FolderOverview, type defaultOverviewSettings } from './obsidian-folder-overview/src/FolderOverview';
|
||||
import { Commands } from './Commands';
|
||||
import type { FileExplorerWorkspaceLeaf } from './globals';
|
||||
import {
|
||||
|
|
@ -21,7 +22,6 @@ import {
|
|||
import { handleCreate } from './events/handleCreate';
|
||||
import { FrontMatterTitlePluginHandler } from './events/FrontMatterTitle';
|
||||
import { FolderOverviewSettings } from './obsidian-folder-overview/src/modals/Settings';
|
||||
import { FolderOverview } from './obsidian-folder-overview/src/FolderOverview';
|
||||
import { TabManager } from './events/TabManager';
|
||||
import './functions/ListComponent';
|
||||
import { handleDelete } from './events/handleDelete';
|
||||
|
|
@ -36,26 +36,65 @@ import { updateOverviewView, updateViewDropdown } from './obsidian-folder-overvi
|
|||
import { FvIndexDB } from './obsidian-folder-overview/src/utils/IndexDB';
|
||||
import { updateAllOverviews } from './obsidian-folder-overview/src/utils/functions';
|
||||
|
||||
interface FileExplorerPluginLike extends Plugin {
|
||||
revealInFolder: (file: TAbstractFile) => void;
|
||||
}
|
||||
|
||||
interface DragManagerLike {
|
||||
draggable?: {
|
||||
file?: TAbstractFile;
|
||||
type?: string;
|
||||
} | null;
|
||||
setAction(action: string): void;
|
||||
}
|
||||
|
||||
interface ClipboardManagerLike {
|
||||
app: App & {
|
||||
dragManager?: DragManagerLike;
|
||||
};
|
||||
handleDragOver: (evt: DragEvent, ...args: unknown[]) => void;
|
||||
handleDrop: (evt: DragEvent, ...args: unknown[]) => void;
|
||||
}
|
||||
|
||||
interface EditModeLike {
|
||||
clipboardManager: ClipboardManagerLike;
|
||||
}
|
||||
|
||||
interface ViewWithEditModes {
|
||||
editMode?: EditModeLike;
|
||||
sourceMode?: EditModeLike;
|
||||
}
|
||||
|
||||
interface ActiveEditorLike {
|
||||
editMode?: EditModeLike;
|
||||
}
|
||||
|
||||
type LegacySettingsData = Partial<FolderNotesSettings> & {
|
||||
allowWhitespaceCollapsing?: boolean;
|
||||
defaultOverview?: defaultOverviewSettings;
|
||||
};
|
||||
|
||||
export default class FolderNotesPlugin extends Plugin {
|
||||
settings: FolderNotesSettings;
|
||||
settingsTab: SettingsTab;
|
||||
activeFolderDom: HTMLElement | null;
|
||||
activeFileExplorer: FileExplorerWorkspaceLeaf;
|
||||
settings!: FolderNotesSettings;
|
||||
settingsTab!: SettingsTab;
|
||||
activeFolderDom!: HTMLElement | null;
|
||||
activeFileExplorer!: FileExplorerWorkspaceLeaf;
|
||||
fmtpHandler: FrontMatterTitlePluginHandler | null = null;
|
||||
hoveredElement: HTMLElement | null = null;
|
||||
mouseEvent: MouseEvent | null = null;
|
||||
hoverLinkTriggered = false;
|
||||
tabManager: TabManager;
|
||||
tabManager!: TabManager;
|
||||
settingsOpened = false;
|
||||
askModalCurrentlyOpen = false;
|
||||
fvIndexDB: FvIndexDB;
|
||||
fvIndexDB!: FvIndexDB;
|
||||
|
||||
async onload(): Promise<void> {
|
||||
// eslint-disable-next-line obsidianmd/rule-custom-message
|
||||
console.log('loading folder notes plugin');
|
||||
await this.loadSettings();
|
||||
this.settingsTab = new SettingsTab(this.app, this);
|
||||
this.addSettingTab(this.settingsTab);
|
||||
this.saveSettings();
|
||||
await this.saveSettings();
|
||||
this.fvIndexDB = new FvIndexDB(this);
|
||||
|
||||
// Add CSS Classes
|
||||
|
|
@ -64,7 +103,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
new Commands(this.app, this).registerCommands();
|
||||
registerOverviewCommands(this);
|
||||
|
||||
this.app.workspace.onLayoutReady(this.onLayoutReady.bind(this));
|
||||
this.app.workspace.onLayoutReady(() => this.onLayoutReady());
|
||||
|
||||
if (!this.settings.persistentSettingsTab.afterRestart) {
|
||||
this.settings.settingsTab = 'general';
|
||||
|
|
@ -93,7 +132,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
this.hoverLinkTriggered = true;
|
||||
});
|
||||
|
||||
this.registerEvent(this.app.workspace.on('file-open', async (openFile: TFile | null) => {
|
||||
this.registerEvent(this.app.workspace.on('file-open', (openFile: TFile | null) => {
|
||||
removeActiveFolder(this);
|
||||
|
||||
if (!openFile || !openFile.basename) { return; }
|
||||
|
|
@ -109,7 +148,9 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
}));
|
||||
|
||||
this.registerEvent(this.app.vault.on('create', (file: TAbstractFile) => {
|
||||
handleCreate(file, this);
|
||||
handleCreate(file, this).catch((err) => {
|
||||
console.error(err); new Notice('Error handling file creation');
|
||||
});
|
||||
this.handleVaultChange();
|
||||
}));
|
||||
|
||||
|
|
@ -132,39 +173,43 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
}
|
||||
|
||||
addSettingCssClasses(): void {
|
||||
document.body.classList.add('folder-notes-plugin');
|
||||
if (this.settings.hideFolderNote) { document.body.classList.add('hide-folder-note'); }
|
||||
activeDocument.body.classList.add('folder-notes-plugin');
|
||||
if (this.settings.hideFolderNote) { activeDocument.body.classList.add('hide-folder-note'); }
|
||||
if (this.settings.hideCollapsingIconForEmptyFolders) {
|
||||
document.body.classList.add('fn-hide-empty-collapse-icon');
|
||||
activeDocument.body.classList.add('fn-hide-empty-collapse-icon');
|
||||
}
|
||||
if (this.settings.hideFolderNoteNameInPath) {
|
||||
document.body.classList.add('folder-note-hide-name-path');
|
||||
activeDocument.body.classList.add('folder-note-hide-name-path');
|
||||
}
|
||||
if (this.settings.underlineFolder) {
|
||||
activeDocument.body.classList.add('folder-note-underline');
|
||||
}
|
||||
if (this.settings.boldName) { activeDocument.body.classList.add('folder-note-bold'); }
|
||||
if (this.settings.cursiveName) { activeDocument.body.classList.add('folder-note-cursive'); }
|
||||
if (this.settings.boldNameInPath) {
|
||||
activeDocument.body.classList.add('folder-note-bold-path');
|
||||
}
|
||||
if (this.settings.underlineFolder) { document.body.classList.add('folder-note-underline'); }
|
||||
if (this.settings.boldName) { document.body.classList.add('folder-note-bold'); }
|
||||
if (this.settings.cursiveName) { document.body.classList.add('folder-note-cursive'); }
|
||||
if (this.settings.boldNameInPath) { document.body.classList.add('folder-note-bold-path'); }
|
||||
if (this.settings.cursiveNameInPath) {
|
||||
document.body.classList.add('folder-note-cursive-path');
|
||||
activeDocument.body.classList.add('folder-note-cursive-path');
|
||||
}
|
||||
if (this.settings.underlineFolderInPath) {
|
||||
document.body.classList.add('folder-note-underline-path');
|
||||
activeDocument.body.classList.add('folder-note-underline-path');
|
||||
}
|
||||
if (this.settings.stopWhitespaceCollapsing) {
|
||||
document.body.classList.add('fn-whitespace-stop-collapsing');
|
||||
activeDocument.body.classList.add('fn-whitespace-stop-collapsing');
|
||||
}
|
||||
if (this.settings.hideCollapsingIcon) {
|
||||
document.body.classList.add('fn-hide-collapse-icon');
|
||||
activeDocument.body.classList.add('fn-hide-collapse-icon');
|
||||
}
|
||||
if (this.settings.ignoreAttachmentFolder) {
|
||||
document.body.classList.add('fn-ignore-attachment-folder');
|
||||
activeDocument.body.classList.add('fn-ignore-attachment-folder');
|
||||
}
|
||||
if (!this.settings.highlightFolder) {
|
||||
document.body.classList.add('disable-folder-highlight');
|
||||
activeDocument.body.classList.add('disable-folder-highlight');
|
||||
}
|
||||
|
||||
if (requireApiVersion('1.7.2')) {
|
||||
document.body.classList.add('version-1-7-2');
|
||||
activeDocument.body.classList.add('version-1-7-2');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,12 +233,12 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
this.tabManager = new TabManager(this);
|
||||
this.tabManager.updateTabs();
|
||||
|
||||
this.registerDomEvent(document, 'click', (evt: MouseEvent) => {
|
||||
this.registerDomEvent(activeDocument, 'click', (evt: MouseEvent) => {
|
||||
this.handleFileExplorerClick(evt);
|
||||
}, true);
|
||||
|
||||
// Handle middle mouse button clicks
|
||||
this.registerDomEvent(document, 'auxclick', (evt: MouseEvent) => {
|
||||
this.registerDomEvent(activeDocument, 'auxclick', (evt: MouseEvent) => {
|
||||
const rightClick = 2;
|
||||
if (evt.button === rightClick) return;
|
||||
this.handleFileExplorerClick(evt);
|
||||
|
|
@ -201,26 +246,32 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
|
||||
const fileExplorerPlugin = this.app.internalPlugins.getEnabledPluginById('file-explorer');
|
||||
if (fileExplorerPlugin) {
|
||||
const originalRevealInFolder = fileExplorerPlugin.revealInFolder
|
||||
.bind(fileExplorerPlugin);
|
||||
fileExplorerPlugin.revealInFolder = (file: TAbstractFile): void => {
|
||||
const fileExplorer = fileExplorerPlugin as unknown as FileExplorerPluginLike;
|
||||
const originalRevealInFolder =
|
||||
fileExplorer.revealInFolder as unknown as FileExplorerPluginLike['revealInFolder'];
|
||||
fileExplorer.revealInFolder = (file: TAbstractFile): void => {
|
||||
if (file instanceof TFile) {
|
||||
const folder = getFolder(this, file);
|
||||
if (folder instanceof TFolder) {
|
||||
const folderNote = getFolderNote(this, folder.path);
|
||||
if (!folderNote || folderNote.path !== file.path) {
|
||||
return originalRevealInFolder.call(fileExplorerPlugin, file);
|
||||
originalRevealInFolder(file);
|
||||
return;
|
||||
}
|
||||
document.body.classList.remove('hide-folder-note');
|
||||
originalRevealInFolder.call(fileExplorerPlugin, folder);
|
||||
activeDocument.body.classList.remove('hide-folder-note');
|
||||
originalRevealInFolder(folder);
|
||||
const FOLDER_REVEAL_DELAY = 100;
|
||||
setTimeout(() => {
|
||||
document.body.classList.add('hide-folder-note');
|
||||
window.setTimeout(() => {
|
||||
activeDocument.body.classList.add('hide-folder-note');
|
||||
}, FOLDER_REVEAL_DELAY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return originalRevealInFolder.call(fileExplorerPlugin, file);
|
||||
if (file instanceof TFolder || file instanceof TFile) {
|
||||
originalRevealInFolder(file);
|
||||
return;
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -229,25 +280,27 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
|
||||
if (!view) { return; }
|
||||
|
||||
// @ts-expect-error use internal API
|
||||
const editMode = view.editMode ?? view.sourceMode
|
||||
// @ts-expect-error use internal API
|
||||
?? this.app.workspace.activeEditor?.editMode;
|
||||
const viewWithEditModes = view as ViewWithEditModes;
|
||||
const activeEditor = this.app.workspace.activeEditor as ActiveEditorLike | undefined;
|
||||
const editMode = viewWithEditModes.editMode ?? viewWithEditModes.sourceMode
|
||||
?? activeEditor?.editMode;
|
||||
|
||||
const plugin = this;
|
||||
if (!editMode) { return; }
|
||||
|
||||
const clipboardProto = editMode.clipboardManager.constructor.prototype;
|
||||
const { clipboardManager } = editMode;
|
||||
const clipboardProto = Object.getPrototypeOf(clipboardManager) as ClipboardManagerLike;
|
||||
|
||||
const originalHandleDragOver = clipboardProto.handleDragOver;
|
||||
const originalHandleDrop = clipboardProto.handleDrop;
|
||||
const originalHandleDragOver =
|
||||
clipboardProto.handleDragOver as unknown as ClipboardManagerLike['handleDragOver'];
|
||||
const originalHandleDrop =
|
||||
clipboardProto.handleDrop as unknown as ClipboardManagerLike['handleDrop'];
|
||||
|
||||
clipboardProto.handleDragOver = function (evt: DragEvent, ...args: unknown[]): void {
|
||||
const { dragManager } = this.app;
|
||||
clipboardProto.handleDragOver = (evt: DragEvent, ...args: unknown[]): void => {
|
||||
const { dragManager } = clipboardManager.app;
|
||||
const draggable = dragManager?.draggable;
|
||||
|
||||
if (draggable?.file instanceof TFolder) {
|
||||
const folderNote = getFolderNote(plugin, draggable.file.path);
|
||||
const folderNote = getFolderNote(this, draggable.file.path);
|
||||
if (folderNote) {
|
||||
dragManager.setAction(
|
||||
window.i18next.t('interface.drag-and-drop.insert-link-here'),
|
||||
|
|
@ -256,22 +309,22 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
return originalHandleDragOver.call(this, evt, ...args);
|
||||
originalHandleDragOver(evt, ...args);
|
||||
};
|
||||
|
||||
clipboardProto.handleDrop = function (evt: DragEvent, ...args: unknown[]): void {
|
||||
const { dragManager } = this.app;
|
||||
clipboardProto.handleDrop = (evt: DragEvent, ...args: unknown[]): void => {
|
||||
const { dragManager } = clipboardManager.app;
|
||||
const draggable = dragManager?.draggable;
|
||||
|
||||
if (draggable?.file instanceof TFolder) {
|
||||
const folderNote = getFolderNote(plugin, draggable.file.path);
|
||||
const folderNote = getFolderNote(this, draggable.file.path);
|
||||
if (folderNote) {
|
||||
draggable.file = folderNote;
|
||||
draggable.type = 'file';
|
||||
}
|
||||
}
|
||||
|
||||
return originalHandleDrop.call(this, evt, ...args);
|
||||
originalHandleDrop(evt, ...args);
|
||||
};
|
||||
|
||||
if (this.settings.fvGlobalSettings.autoUpdateLinks) {
|
||||
|
|
@ -283,7 +336,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
if (!this.settings.fvGlobalSettings.autoUpdateLinks) return;
|
||||
const DEBOUNCE_DELAY = 2000;
|
||||
debounce(() => {
|
||||
updateAllOverviews(this);
|
||||
void updateAllOverviews(this);
|
||||
}, DEBOUNCE_DELAY, true)();
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +367,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
evt.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
openFolderNote(this, folderNote, evt);
|
||||
void openFolderNote(this, folderNote, evt);
|
||||
}
|
||||
|
||||
private isMobileClickDisabled(): boolean {
|
||||
|
|
@ -325,9 +378,12 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
folderTitleEl: HTMLElement | null;
|
||||
onlyClickedOnFolderTitle: boolean;
|
||||
} {
|
||||
const folderTitleEl = target.closest('.nav-folder-title') as HTMLElement | null;
|
||||
const folderTitleEl = target.closest('.nav-folder-title');
|
||||
const onlyClickedOnFolderTitle = !!target.closest('.nav-folder-title-content');
|
||||
return { folderTitleEl, onlyClickedOnFolderTitle };
|
||||
return {
|
||||
folderTitleEl: folderTitleEl instanceof HTMLElement ? folderTitleEl : null,
|
||||
onlyClickedOnFolderTitle,
|
||||
};
|
||||
}
|
||||
|
||||
private shouldIgnoreClickByWhitespaceOrCollapse(
|
||||
|
|
@ -358,9 +414,9 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
}
|
||||
|
||||
private createNoteAndMark(folderPath: string): void {
|
||||
createFolderNote(this, folderPath, true, undefined, true);
|
||||
addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, this);
|
||||
removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, this);
|
||||
void createFolderNote(this, folderPath, true, undefined, true);
|
||||
void addCSSClassToFileExplorerEl(folderPath, 'has-folder-note', false, this);
|
||||
void removeCSSClassFromFileExplorerEL(folderPath, 'has-not-folder-note', false, this);
|
||||
}
|
||||
|
||||
private shouldOpenNote(usedCtrl: boolean, evt: MouseEvent): boolean {
|
||||
|
|
@ -380,7 +436,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
new FolderOverviewSettings(
|
||||
this.app,
|
||||
this,
|
||||
parseYaml(source),
|
||||
parseYaml(source) as defaultOverviewSettings,
|
||||
ctx,
|
||||
el,
|
||||
this.settings.defaultOverview,
|
||||
|
|
@ -404,7 +460,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
el,
|
||||
defaultOverview,
|
||||
);
|
||||
folderOverview.create(this, el, ctx);
|
||||
void folderOverview.create(this, el, ctx);
|
||||
} else {
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
const folderOverview = new FolderOverview(
|
||||
|
|
@ -414,7 +470,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
el,
|
||||
this.settings.defaultOverview,
|
||||
);
|
||||
folderOverview.create(this, el, ctx);
|
||||
void folderOverview.create(this, el, ctx);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -438,7 +494,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
}
|
||||
|
||||
if (!leaf) return;
|
||||
workspace.revealLeaf(leaf);
|
||||
void workspace.revealLeaf(leaf);
|
||||
}
|
||||
|
||||
updateOverviewView: typeof updateOverviewView = updateOverviewView;
|
||||
|
|
@ -451,12 +507,12 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
|| attachmentFolderPath === '';
|
||||
const threshold = this.settings.storageLocation === 'insideFolder' ? 1 : 0;
|
||||
if (folder.children.length === 0) {
|
||||
addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this);
|
||||
void addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this);
|
||||
}
|
||||
attachmentFolderPath = `${folder.path}/${cleanAttachmentFolderPath}`;
|
||||
|
||||
if (folder.children.length === threshold) {
|
||||
addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this);
|
||||
void addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this);
|
||||
return true;
|
||||
} else if (folder.children.length > threshold) {
|
||||
if (attachmentsAreInRootFolder) {
|
||||
|
|
@ -469,12 +525,12 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
attachmentFolder instanceof TFolder &&
|
||||
folder.children.length <= threshold + 1
|
||||
) {
|
||||
addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this);
|
||||
addCSSClassToFileExplorerEl(
|
||||
void addCSSClassToFileExplorerEl(folder.path, 'fn-empty-folder', false, this);
|
||||
void addCSSClassToFileExplorerEl(
|
||||
folder.path, 'fn-has-attachment-folder',
|
||||
false, this,
|
||||
);
|
||||
addCSSClassToFileExplorerEl(
|
||||
void addCSSClassToFileExplorerEl(
|
||||
folder.path, 'fn-has-attachment-folder',
|
||||
true, this,
|
||||
);
|
||||
|
|
@ -499,7 +555,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
let fileExplorerItem = getFileExplorerElement(folder.path, this);
|
||||
if (!fileExplorerItem) {
|
||||
if (waitForCreate && count < MAX_RETRY_COUNT) {
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, RETRY_DELAY_MS));
|
||||
await new Promise<void>((resolve) => window.setTimeout(resolve, RETRY_DELAY_MS));
|
||||
void this.changeFolderNameInExplorer(folder, newName, waitForCreate, count + 1);
|
||||
return;
|
||||
}
|
||||
|
|
@ -509,11 +565,11 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
fileExplorerItem = fileExplorerItem?.querySelector('div.nav-folder-title-content');
|
||||
if (!fileExplorerItem) { return; }
|
||||
if (this.settings.frontMatterTitle.explorer && this.settings.frontMatterTitle.enabled) {
|
||||
(fileExplorerItem as HTMLElement).innerText = newName;
|
||||
(fileExplorerItem as HTMLElement).setAttribute('old-name', folder.name);
|
||||
(fileExplorerItem).innerText = newName;
|
||||
(fileExplorerItem).setAttribute('old-name', folder.name);
|
||||
} else {
|
||||
(fileExplorerItem as HTMLElement).innerText = folder.name;
|
||||
(fileExplorerItem as HTMLElement).removeAttribute('old-name');
|
||||
(fileExplorerItem).innerText = folder.name;
|
||||
(fileExplorerItem).removeAttribute('old-name');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -534,7 +590,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
*/
|
||||
updateAllBreadcrumbs(remove?: boolean): void {
|
||||
if (!this.settings.frontMatterTitle.path && !remove) { return; }
|
||||
const viewHeaderItems = document.querySelectorAll('span.view-header-breadcrumb');
|
||||
const viewHeaderItems = activeDocument.querySelectorAll('span.view-header-breadcrumb');
|
||||
const files = this.app.vault.getAllLoadedFiles().filter((file) => file instanceof TFolder);
|
||||
viewHeaderItems.forEach((item) => {
|
||||
if (!item.hasAttribute('data-path')) { return; }
|
||||
|
|
@ -554,10 +610,10 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
|
||||
onunload(): void {
|
||||
unregisterFileExplorerObserver();
|
||||
document.body.classList.remove('folder-notes-plugin');
|
||||
document.body.classList.remove('folder-note-underline');
|
||||
document.body.classList.remove('hide-folder-note');
|
||||
document.body.classList.remove('fn-whitespace-stop-collapsing');
|
||||
activeDocument.body.classList.remove('folder-notes-plugin');
|
||||
activeDocument.body.classList.remove('folder-note-underline');
|
||||
activeDocument.body.classList.remove('hide-folder-note');
|
||||
activeDocument.body.classList.remove('fn-whitespace-stop-collapsing');
|
||||
removeActiveFolder(this);
|
||||
if (this.fmtpHandler) {
|
||||
this.fmtpHandler.deleteEvent();
|
||||
|
|
@ -565,7 +621,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
}
|
||||
|
||||
async loadSettings(): Promise<void> {
|
||||
const data = await this.loadData();
|
||||
const data = await this.loadData() as LegacySettingsData | null;
|
||||
if (data) {
|
||||
if (data.allowWhitespaceCollapsing === true) {
|
||||
data.stopWhitespaceCollapsing = false;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export default class AddSupportedFileModal extends Modal {
|
|||
}),
|
||||
);
|
||||
}
|
||||
async onClose(): Promise<void> {
|
||||
onClose(): void {
|
||||
if (this.name.toLocaleLowerCase() === 'markdown') {
|
||||
this.name = 'md';
|
||||
}
|
||||
|
|
@ -50,10 +50,13 @@ export default class AddSupportedFileModal extends Modal {
|
|||
new Notice('This extension is already supported');
|
||||
return;
|
||||
} else {
|
||||
await this.list.addValue(this.name.toLowerCase());
|
||||
this.settingsTab.display();
|
||||
this.plugin.saveSettings();
|
||||
contentEl.empty();
|
||||
// Run async operations without returning a Promise from onClose
|
||||
void (async (): Promise<void> => {
|
||||
await this.list.addValue(this.name.toLowerCase());
|
||||
this.settingsTab.display();
|
||||
await this.plugin.saveSettings();
|
||||
contentEl.empty();
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export class AskForExtensionModal extends FuzzySuggestModal<string> {
|
|||
onChooseItem(item: string, _evt: MouseEvent | KeyboardEvent): void {
|
||||
this.plugin.askModalCurrentlyOpen = false;
|
||||
this.extension = '.' + item;
|
||||
createFolderNote(
|
||||
void createFolderNote(
|
||||
this.plugin,
|
||||
this.folderPath,
|
||||
this.openFile,
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ export default class ExistingFolderNoteModal extends Modal {
|
|||
text: 'Rename and don\'t ask again',
|
||||
});
|
||||
confirmButton.classList.add('mod-warning', 'fn-confirmation-modal-button');
|
||||
confirmButton.addEventListener('click', async () => {
|
||||
confirmButton.addEventListener('click', () => {
|
||||
this.plugin.settings.showRenameConfirmation = false;
|
||||
this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
this.close();
|
||||
turnIntoFolderNote(this.plugin, this.file, this.folder, this.folderNote, true);
|
||||
});
|
||||
|
|
@ -69,14 +69,14 @@ export default class ExistingFolderNoteModal extends Modal {
|
|||
}
|
||||
const button = buttonContainer.createEl('button', { text: 'Rename' });
|
||||
button.classList.add('mod-warning', 'fn-confirmation-modal-button');
|
||||
button.addEventListener('click', async () => {
|
||||
this.plugin.saveSettings();
|
||||
button.addEventListener('click', () => {
|
||||
void this.plugin.saveSettings();
|
||||
this.close();
|
||||
turnIntoFolderNote(this.plugin, this.file, this.folder, this.folderNote, true);
|
||||
});
|
||||
button.focus();
|
||||
const cancelButton = buttonContainer.createEl('button', { text: 'Cancel' });
|
||||
cancelButton.addEventListener('click', async () => {
|
||||
cancelButton.addEventListener('click', () => {
|
||||
this.close();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export async function renderExcludeFolders(settingsTab: SettingsTab): Promise<vo
|
|||
.setHeading()
|
||||
.setClass('fn-excluded-folder-heading')
|
||||
.setName('Manage excluded folders');
|
||||
const desc3 = document.createDocumentFragment();
|
||||
const desc3 = activeDocument.createDocumentFragment();
|
||||
desc3.append(
|
||||
'Add {regex} at the beginning of the folder name to use a regex pattern.',
|
||||
desc3.createEl('br'),
|
||||
|
|
@ -28,12 +28,12 @@ export async function renderExcludeFolders(settingsTab: SettingsTab): Promise<vo
|
|||
'Use * after the folder name to exclude folders that start with the folder name.',
|
||||
);
|
||||
manageExcluded.setDesc(desc3);
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
manageExcluded.infoEl.appendText('The regexes and wildcards are only for the folder name, not the path.');
|
||||
manageExcluded.infoEl.createEl('br');
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
manageExcluded.infoEl.appendText('If you want to switch to a folder path delete the pattern first.');
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
manageExcluded.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed';
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
settingsTab.plugin.settings.hideFolderNote = value;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
if (value) {
|
||||
document.body.classList.add('hide-folder-note');
|
||||
activeDocument.body.classList.add('hide-folder-note');
|
||||
} else {
|
||||
document.body.classList.remove('hide-folder-note');
|
||||
activeDocument.body.classList.remove('hide-folder-note');
|
||||
}
|
||||
settingsTab.display();
|
||||
}),
|
||||
|
|
@ -46,9 +46,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
.setValue(!settingsTab.plugin.settings.stopWhitespaceCollapsing)
|
||||
.onChange(async (value) => {
|
||||
if (!value) {
|
||||
document.body.classList.add('fn-whitespace-stop-collapsing');
|
||||
activeDocument.body.classList.add('fn-whitespace-stop-collapsing');
|
||||
} else {
|
||||
document.body.classList.remove('fn-whitespace-stop-collapsing');
|
||||
activeDocument.body.classList.remove('fn-whitespace-stop-collapsing');
|
||||
}
|
||||
settingsTab.plugin.settings.stopWhitespaceCollapsing = !value;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
|
|
@ -119,9 +119,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.highlightFolder = value;
|
||||
if (!value) {
|
||||
document.body.classList.add('disable-folder-highlight');
|
||||
activeDocument.body.classList.add('disable-folder-highlight');
|
||||
} else {
|
||||
document.body.classList.remove('disable-folder-highlight');
|
||||
activeDocument.body.classList.remove('disable-folder-highlight');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
@ -136,9 +136,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.hideCollapsingIcon = value;
|
||||
if (value) {
|
||||
document.body.classList.add('fn-hide-collapse-icon');
|
||||
activeDocument.body.classList.add('fn-hide-collapse-icon');
|
||||
} else {
|
||||
document.body.classList.remove('fn-hide-collapse-icon');
|
||||
activeDocument.body.classList.remove('fn-hide-collapse-icon');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
settingsTab.display();
|
||||
|
|
@ -155,9 +155,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
settingsTab.plugin.settings.hideCollapsingIconForEmptyFolders = value;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
if (value) {
|
||||
document.body.classList.add('fn-hide-empty-collapse-icon');
|
||||
activeDocument.body.classList.add('fn-hide-empty-collapse-icon');
|
||||
} else {
|
||||
document.body.classList.remove('fn-hide-empty-collapse-icon');
|
||||
activeDocument.body.classList.remove('fn-hide-empty-collapse-icon');
|
||||
}
|
||||
settingsTab.display();
|
||||
},
|
||||
|
|
@ -171,9 +171,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
.setValue(settingsTab.plugin.settings.ignoreAttachmentFolder)
|
||||
.onChange(async (value) => {
|
||||
if (value) {
|
||||
document.body.classList.add('fn-ignore-attachment-folder');
|
||||
activeDocument.body.classList.add('fn-ignore-attachment-folder');
|
||||
} else {
|
||||
document.body.classList.remove('fn-ignore-attachment-folder');
|
||||
activeDocument.body.classList.remove('fn-ignore-attachment-folder');
|
||||
}
|
||||
settingsTab.plugin.settings.ignoreAttachmentFolder = value;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
|
|
@ -190,9 +190,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.underlineFolder = value;
|
||||
if (value) {
|
||||
document.body.classList.add('folder-note-underline');
|
||||
activeDocument.body.classList.add('folder-note-underline');
|
||||
} else {
|
||||
document.body.classList.remove('folder-note-underline');
|
||||
activeDocument.body.classList.remove('folder-note-underline');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
@ -207,9 +207,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.boldName = value;
|
||||
if (value) {
|
||||
document.body.classList.add('folder-note-bold');
|
||||
activeDocument.body.classList.add('folder-note-bold');
|
||||
} else {
|
||||
document.body.classList.remove('folder-note-bold');
|
||||
activeDocument.body.classList.remove('folder-note-bold');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
@ -224,9 +224,9 @@ export async function renderFileExplorer(settingsTab: SettingsTab): Promise<void
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.cursiveName = value;
|
||||
if (value) {
|
||||
document.body.classList.add('folder-note-cursive');
|
||||
activeDocument.body.classList.add('folder-note-cursive');
|
||||
} else {
|
||||
document.body.classList.remove('folder-note-cursive');
|
||||
activeDocument.body.classList.remove('folder-note-cursive');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -36,11 +36,12 @@ export async function renderFolderOverview(settingsTab: SettingsTab): Promise<vo
|
|||
span.setAttr('style', `color: ${accentColor};`);
|
||||
pEl.appendChild(span);
|
||||
|
||||
createOverviewSettings(
|
||||
void createOverviewSettings(
|
||||
containerEl,
|
||||
defaultOverviewSettings,
|
||||
plugin,
|
||||
plugin.settings.defaultOverview,
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
settingsTab.display,
|
||||
undefined,
|
||||
undefined,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable max-len */
|
||||
import { Setting, Platform } from 'obsidian';
|
||||
import type { SettingsTab } from './SettingsTab';
|
||||
|
|
@ -10,7 +11,7 @@ import { refreshAllFolderStyles } from '../functions/styleFunctions';
|
|||
import BackupWarningModal from './modals/BackupWarning';
|
||||
import RenameFolderNotesModal from './modals/RenameFns';
|
||||
|
||||
let debounceTimer: NodeJS.Timeout;
|
||||
let debounceTimer: ReturnType<typeof setTimeout>;
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
||||
|
|
@ -26,9 +27,9 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
settingsTab.plugin.settings.folderNoteName = value;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
|
||||
clearTimeout(debounceTimer);
|
||||
window.clearTimeout(debounceTimer);
|
||||
const FOLDER_NOTE_NAME_DEBOUNCE_MS = 2000;
|
||||
debounceTimer = setTimeout(() => {
|
||||
debounceTimer = window.setTimeout(() => {
|
||||
if (!value.includes('{{folder_name}}')) {
|
||||
if (!settingsTab.showFolderNameInTabTitleSetting) {
|
||||
settingsTab.display();
|
||||
|
|
@ -62,8 +63,8 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
|
||||
if (!settingsTab.plugin.settings.folderNoteName.includes('{{folder_name}}')) {
|
||||
new Setting(containerEl)
|
||||
.setName('Display Folder Name in Tab Title')
|
||||
.setDesc('Use the actual folder name in the tab title instead of the custom folder note name (e.g., "Folder Note").')
|
||||
.setName('Display folder name in tab title')
|
||||
.setDesc('Use the actual folder name in the tab title instead of the custom folder note name (e.g., "folder note").')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(settingsTab.plugin.settings.tabManagerEnabled)
|
||||
|
|
@ -83,12 +84,12 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
|
||||
new Setting(containerEl)
|
||||
.setName('Default file type for new folder notes')
|
||||
.setDesc('Choose the default file type (canvas, markdown, ...) used when creating new folder notes.')
|
||||
.setDesc('Choose the default file type (canvas, Markdown, ...) used when creating new folder notes.')
|
||||
.addDropdown((dropdown) => {
|
||||
dropdown.addOption('.ask', 'ask for file type');
|
||||
dropdown.addOption('.ask', 'Ask for file type');
|
||||
settingsTab.plugin.settings.supportedFileTypes.forEach((type) => {
|
||||
if (type === '.md' || type === 'md') {
|
||||
dropdown.addOption('.md', 'markdown');
|
||||
dropdown.addOption('.md', 'Markdown');
|
||||
} else {
|
||||
dropdown.addOption('.' + type, type);
|
||||
}
|
||||
|
|
@ -101,7 +102,7 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
settingsTab.plugin.settings.folderNoteType !== '.ask'
|
||||
) {
|
||||
settingsTab.plugin.settings.folderNoteType = '.md';
|
||||
settingsTab.plugin.saveSettings();
|
||||
void settingsTab.plugin.saveSettings();
|
||||
}
|
||||
|
||||
let defaultType = settingsTab.plugin.settings.folderNoteType.startsWith('.')
|
||||
|
|
@ -118,16 +119,16 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
|
||||
dropdown
|
||||
.setValue(defaultType)
|
||||
.onChange(async (value: '.md' | '.canvas') => {
|
||||
settingsTab.plugin.settings.folderNoteType = value;
|
||||
settingsTab.plugin.saveSettings();
|
||||
settingsTab.display();
|
||||
.onChange(async (value: string) => {
|
||||
settingsTab.plugin.settings.folderNoteType = value as '.md' | '.canvas' | '.ask';
|
||||
void settingsTab.plugin.saveSettings();
|
||||
void settingsTab.display();
|
||||
});
|
||||
});
|
||||
|
||||
const setting0 = new Setting(containerEl);
|
||||
setting0.setName('Supported file types');
|
||||
const desc0 = document.createDocumentFragment();
|
||||
const desc0 = activeDocument.createDocumentFragment();
|
||||
desc0.append(
|
||||
'Specify which file types are allowed as folder notes. Applies to both new and existing folders. Adding many types may affect performance.',
|
||||
);
|
||||
|
|
@ -137,10 +138,10 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
settingsTab.plugin.settings.supportedFileTypes || [],
|
||||
['md', 'canvas'],
|
||||
);
|
||||
list.on('update', async (values: string[]) => {
|
||||
settingsTab.plugin.settings.supportedFileTypes = values;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
settingsTab.display();
|
||||
list.on('update', (values: unknown) => {
|
||||
settingsTab.plugin.settings.supportedFileTypes = values as string[];
|
||||
void settingsTab.plugin.saveSettings();
|
||||
void settingsTab.display();
|
||||
});
|
||||
|
||||
if (
|
||||
|
|
@ -170,12 +171,12 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
settingsTab.app,
|
||||
settingsTab.plugin,
|
||||
settingsTab,
|
||||
list as ListComponent,
|
||||
list,
|
||||
).open();
|
||||
}
|
||||
await list.addValue(value.toLowerCase());
|
||||
settingsTab.display();
|
||||
settingsTab.plugin.saveSettings();
|
||||
void settingsTab.display();
|
||||
void settingsTab.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
|
@ -188,7 +189,7 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
settingsTab.app,
|
||||
settingsTab.plugin,
|
||||
settingsTab,
|
||||
list as ListComponent,
|
||||
list,
|
||||
).open();
|
||||
}),
|
||||
);
|
||||
|
|
@ -226,7 +227,10 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
.addOption('insideFolder', 'Inside the folder')
|
||||
.addOption('parentFolder', 'In the parent folder')
|
||||
.setValue(settingsTab.plugin.settings.storageLocation)
|
||||
.onChange(async (value: 'insideFolder' | 'parentFolder' | 'vaultFolder') => {
|
||||
.onChange(async (value: string) => {
|
||||
if (value !== 'insideFolder' && value !== 'parentFolder' && value !== 'vaultFolder') {
|
||||
return;
|
||||
}
|
||||
settingsTab.plugin.settings.storageLocation = value;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
settingsTab.display();
|
||||
|
|
@ -282,7 +286,7 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
);
|
||||
}
|
||||
if (Platform.isDesktopApp) {
|
||||
settingsTab.settingsPage.createEl('h3', { text: 'Keyboard Shortcuts' });
|
||||
settingsTab.settingsPage.createEl('h3', { text: 'Keyboard shortcuts' });
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Key for creating folder note')
|
||||
|
|
@ -308,7 +312,7 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
.setName('Key for opening folder note')
|
||||
.setDesc('Select the combination to open a folder note')
|
||||
.addDropdown((dropdown) => {
|
||||
dropdown.addOption('click', 'Mouse Click');
|
||||
dropdown.addOption('click', 'Mouse click');
|
||||
if (!Platform.isMacOS) {
|
||||
dropdown.addOption('ctrl', 'Ctrl + Click');
|
||||
dropdown.addOption('alt', 'Alt + Click');
|
||||
|
|
@ -356,8 +360,9 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
dropdown.addOption('obsidianTrash', 'Move to Obsidian trash (.trash folder)');
|
||||
dropdown.addOption('delete', 'Delete permanently');
|
||||
dropdown.setValue(settingsTab.plugin.settings.deleteFilesAction);
|
||||
dropdown.onChange(async (value: 'trash' | 'delete' | 'obsidianTrash') => {
|
||||
settingsTab.plugin.settings.deleteFilesAction = value;
|
||||
dropdown.onChange(async (value) => {
|
||||
const v = value as 'trash' | 'delete' | 'obsidianTrash';
|
||||
settingsTab.plugin.settings.deleteFilesAction = v;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
settingsTab.display();
|
||||
});
|
||||
|
|
@ -450,7 +455,7 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
|
||||
new Setting(containerEl)
|
||||
.setName('Auto-create for attachment folders')
|
||||
.setDesc('Also automatically create folder notes for attachment folders (e.g., "Attachments", "Media", etc.).')
|
||||
.setDesc('Also automatically create folder notes for attachment folders (e.g., "attachments", "media", etc.).')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(settingsTab.plugin.settings.autoCreateForAttachmentFolder)
|
||||
|
|
@ -475,13 +480,13 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
}),
|
||||
);
|
||||
|
||||
settingsTab.settingsPage.createEl('h3', { text: 'Integration & Compatibility' });
|
||||
settingsTab.settingsPage.createEl('h3', { text: 'Integration & compatibility' });
|
||||
|
||||
const desc1 = document.createDocumentFragment();
|
||||
const desc1 = activeDocument.createDocumentFragment();
|
||||
|
||||
const link = document.createElement('a');
|
||||
const link = activeDocument.createElement('a');
|
||||
link.href = 'https://github.com/snezhig/obsidian-front-matter-title';
|
||||
link.textContent = 'front matter title plugin';
|
||||
link.textContent = 'Front matter title plugin';
|
||||
link.target = '_blank';
|
||||
|
||||
desc1.append(
|
||||
|
|
@ -507,7 +512,7 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
settingsTab.plugin.updateAllBreadcrumbs(true);
|
||||
}
|
||||
settingsTab.plugin.app.vault.getFiles().forEach((file) => {
|
||||
settingsTab.plugin.fmtpHandler?.fmptUpdateFileName(
|
||||
void settingsTab.plugin.fmtpHandler?.fmptUpdateFileName(
|
||||
{
|
||||
id: '',
|
||||
result: false,
|
||||
|
|
@ -527,7 +532,7 @@ export async function renderGeneral(settingsTab: SettingsTab): Promise<void> {
|
|||
fmtpSetting.infoEl.appendText('Requires a restart to take effect');
|
||||
fmtpSetting.infoEl.style.color = settingsTab.app.vault.getConfig('accentColor') as string || '#7d5bed';
|
||||
|
||||
settingsTab.settingsPage.createEl('h3', { text: 'Session & Persistence' });
|
||||
settingsTab.settingsPage.createEl('h3', { text: 'Session & persistence' });
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Persist tab after restart')
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export async function renderPath(settingsTab: SettingsTab): Promise<void> {
|
|||
|
||||
if (settingsTab.plugin.settings.openFolderNoteOnClickInPath) {
|
||||
new Setting(containerEl)
|
||||
.setName('Open sidebar when opening a folder note through path (Mobile only)')
|
||||
.setName('Open sidebar when opening a folder note through path (mobile only)')
|
||||
.setDesc('Open the sidebar when opening a folder note through the path on mobile')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
|
|
@ -30,7 +30,7 @@ export async function renderPath(settingsTab: SettingsTab): Promise<void> {
|
|||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Open sidebar when opening a folder note through path (Desktop only)')
|
||||
.setName('Open sidebar when opening a folder note through path (desktop only)')
|
||||
.setDesc('Open the sidebar when opening a folder note through the path on desktop')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
|
|
@ -72,9 +72,9 @@ export async function renderPath(settingsTab: SettingsTab): Promise<void> {
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.underlineFolderInPath = value;
|
||||
if (value) {
|
||||
document.body.classList.add('folder-note-underline-path');
|
||||
activeDocument.body.classList.add('folder-note-underline-path');
|
||||
} else {
|
||||
document.body.classList.remove('folder-note-underline-path');
|
||||
activeDocument.body.classList.remove('folder-note-underline-path');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
@ -89,9 +89,9 @@ export async function renderPath(settingsTab: SettingsTab): Promise<void> {
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.boldNameInPath = value;
|
||||
if (value) {
|
||||
document.body.classList.add('folder-note-bold-path');
|
||||
activeDocument.body.classList.add('folder-note-bold-path');
|
||||
} else {
|
||||
document.body.classList.remove('folder-note-bold-path');
|
||||
activeDocument.body.classList.remove('folder-note-bold-path');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
@ -106,9 +106,9 @@ export async function renderPath(settingsTab: SettingsTab): Promise<void> {
|
|||
.onChange(async (value) => {
|
||||
settingsTab.plugin.settings.cursiveNameInPath = value;
|
||||
if (value) {
|
||||
document.body.classList.add('folder-note-cursive-path');
|
||||
activeDocument.body.classList.add('folder-note-cursive-path');
|
||||
} else {
|
||||
document.body.classList.remove('folder-note-cursive-path');
|
||||
activeDocument.body.classList.remove('folder-note-cursive-path');
|
||||
}
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
@ -121,7 +121,7 @@ export async function renderPath(settingsTab: SettingsTab): Promise<void> {
|
|||
toggle
|
||||
.setValue(settingsTab.plugin.settings.hideFolderNoteNameInPath)
|
||||
.onChange(async (value) => {
|
||||
document.body.classList.toggle('folder-note-hide-name-path', value);
|
||||
activeDocument.body.classList.toggle('folder-note-hide-name-path', value);
|
||||
settingsTab.plugin.settings.hideFolderNoteNameInPath = value;
|
||||
await settingsTab.plugin.saveSettings();
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -211,11 +211,11 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = {
|
|||
};
|
||||
|
||||
export class SettingsTab extends PluginSettingTab {
|
||||
plugin: FolderNotesPlugin;
|
||||
app: App;
|
||||
excludeFolders: ExcludedFolder[];
|
||||
plugin!: FolderNotesPlugin;
|
||||
app!: App;
|
||||
excludeFolders!: ExcludedFolder[];
|
||||
settingsPage!: HTMLElement;
|
||||
showFolderNameInTabTitleSetting: boolean;
|
||||
showFolderNameInTabTitleSetting!: boolean;
|
||||
constructor(app: App, plugin: FolderNotesPlugin) {
|
||||
super(app, plugin);
|
||||
}
|
||||
|
|
@ -246,19 +246,19 @@ export class SettingsTab extends PluginSettingTab {
|
|||
this.settingsPage.empty();
|
||||
switch (tabId.toLocaleLowerCase()) {
|
||||
case this.TABS.GENERAL.id:
|
||||
renderGeneral(this);
|
||||
void renderGeneral(this);
|
||||
break;
|
||||
case this.TABS.FOLDER_OVERVIEW.id:
|
||||
renderFolderOverview(this);
|
||||
void renderFolderOverview(this);
|
||||
break;
|
||||
case this.TABS.EXCLUDE_FOLDERS.id:
|
||||
renderExcludeFolders(this);
|
||||
void renderExcludeFolders(this);
|
||||
break;
|
||||
case this.TABS.FILE_EXPLORER.id:
|
||||
renderFileExplorer(this);
|
||||
void renderFileExplorer(this);
|
||||
break;
|
||||
case this.TABS.PATH.id:
|
||||
renderPath(this);
|
||||
void renderPath(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -298,12 +298,11 @@ export class SettingsTab extends PluginSettingTab {
|
|||
tabEl.addClass('fn-settings-tab-active');
|
||||
}
|
||||
tabEl.addEventListener('click', () => {
|
||||
// @ts-expect-error: tabBar.children may not have removeClass method, but we know it works in this context
|
||||
for (const child of tabBar.children) {
|
||||
child.removeClass('fn-settings-tab-active');
|
||||
(child as HTMLElement).classList.remove('fn-settings-tab-active');
|
||||
if (!plugin) { return; }
|
||||
plugin.settings.settingsTab = tabId.toLocaleLowerCase();
|
||||
plugin.saveSettings();
|
||||
void plugin.saveSettings();
|
||||
}
|
||||
tabEl.addClass('fn-settings-tab-active');
|
||||
if (!settingsTab) { return; }
|
||||
|
|
@ -344,19 +343,19 @@ export class SettingsTab extends PluginSettingTab {
|
|||
if (getFolderPathFromString(folder.path).trim() === '/') {
|
||||
newPath = `${newFolderNoteName}.${folderNote.extension}`;
|
||||
} else {
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
newPath = `${folderNote.parent?.path}/${newFolderNoteName}.${folderNote.extension}`;
|
||||
}
|
||||
} else if (this.plugin.settings.storageLocation === 'insideFolder') {
|
||||
newPath = `${folder.path}/${newFolderNoteName}.${folderNote.extension}`;
|
||||
}
|
||||
|
||||
this.app.fileManager.renameFile(folderNote, newPath);
|
||||
void this.app.fileManager.renameFile(folderNote, newPath);
|
||||
}
|
||||
}
|
||||
|
||||
this.plugin.settings.oldFolderNoteName = this.plugin.settings.folderNoteName;
|
||||
this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
new Notice('Finished updating folder notes');
|
||||
}
|
||||
|
||||
|
|
@ -373,13 +372,13 @@ export class SettingsTab extends PluginSettingTab {
|
|||
} else {
|
||||
newPath = `${getFolderPathFromString(file.path)}/${folderNote.name}`;
|
||||
}
|
||||
this.plugin.app.fileManager.renameFile(folderNote, newPath);
|
||||
void this.plugin.app.fileManager.renameFile(folderNote, newPath);
|
||||
} else if (this.plugin.settings.storageLocation === 'insideFolder') {
|
||||
if (getFolderPathFromString(folderNote.path) === file.path) {
|
||||
return;
|
||||
}
|
||||
const newPath = `${file.path}/${folderNote.name}`;
|
||||
this.plugin.app.fileManager.renameFile(folderNote, newPath);
|
||||
void this.plugin.app.fileManager.renameFile(folderNote, newPath);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default class BackupWarningModal extends Modal {
|
|||
contentEl.createEl('p', { text: this.desc });
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
contentEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).style.color = '#fb464c';
|
||||
contentEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).addClass('fn-warning-text');
|
||||
|
||||
const buttonContainer = contentEl.createDiv({ cls: 'fn-modal-button-container' });
|
||||
const confirmButton = new ButtonComponent(buttonContainer);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'
|
|||
export default class ConfirmationModal extends Modal {
|
||||
plugin: FolderNotesPlugin;
|
||||
app: App;
|
||||
folder: TFolder;
|
||||
folder!: TFolder;
|
||||
extension: string;
|
||||
constructor(app: App, plugin: FolderNotesPlugin) {
|
||||
super(app);
|
||||
|
|
@ -36,7 +36,7 @@ export default class ConfirmationModal extends Modal {
|
|||
contentEl.createEl('h2', { text: 'Create folder note for every folder' });
|
||||
const setting = new Setting(contentEl);
|
||||
// eslint-disable-next-line max-len
|
||||
setting.infoEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).style.color = '#fb464c';
|
||||
setting.infoEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).addClass('fn-warning-text');
|
||||
// eslint-disable-next-line max-len
|
||||
setting.infoEl.createEl('p', { text: 'This feature will create a folder note for every folder in your vault.' });
|
||||
// eslint-disable-next-line max-len
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ export default class RenameFolderNotesModal extends BackupWarningModal {
|
|||
insertCustomHtml(): void {
|
||||
const { contentEl } = this;
|
||||
new Setting(contentEl)
|
||||
.setName('Old Folder Note Name')
|
||||
// eslint-disable-next-line max-len
|
||||
.setName('Old folder note name')
|
||||
.setDesc('Every folder note that matches this name will be renamed to the new folder note name.')
|
||||
.addText((text) => text
|
||||
.setPlaceholder('Enter the old folder note name')
|
||||
|
|
@ -28,8 +27,7 @@ export default class RenameFolderNotesModal extends BackupWarningModal {
|
|||
);
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName('New Folder Note Name')
|
||||
// eslint-disable-next-line max-len
|
||||
.setName('New folder note name')
|
||||
.setDesc('Every folder note that matches the old folder note name will be renamed to this name.')
|
||||
.addText((text) => text
|
||||
.setPlaceholder('Enter the new folder note name')
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
import { type TAbstractFile, TFile } from 'obsidian';
|
||||
import { TextInputSuggest } from './Suggest';
|
||||
import { AbstractInputSuggest, type TAbstractFile, TFile } from 'obsidian';
|
||||
import type FolderNotesPlugin from '../main';
|
||||
export enum FileSuggestMode {
|
||||
TemplateFiles,
|
||||
ScriptFiles,
|
||||
}
|
||||
|
||||
export class FileSuggest extends TextInputSuggest<TFile> {
|
||||
export class FileSuggest extends AbstractInputSuggest<TFile> {
|
||||
plugin: FolderNotesPlugin;
|
||||
|
||||
constructor(
|
||||
public inputEl: HTMLInputElement,
|
||||
plugin: FolderNotesPlugin,
|
||||
public inputEl: HTMLInputElement,
|
||||
plugin: FolderNotesPlugin,
|
||||
) {
|
||||
super(inputEl, plugin);
|
||||
super(plugin.app, inputEl);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
get_error_msg(mode: FileSuggestMode): string {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater
|
||||
|
||||
import { TFolder, type TAbstractFile } from 'obsidian';
|
||||
import { TextInputSuggest } from './Suggest';
|
||||
import { AbstractInputSuggest, TFolder, type TAbstractFile } from 'obsidian';
|
||||
import type FolderNotesPlugin from '../main';
|
||||
export enum FileSuggestMode {
|
||||
TemplateFiles,
|
||||
ScriptFiles,
|
||||
}
|
||||
|
||||
export class FolderSuggest extends TextInputSuggest<TFolder> {
|
||||
export class FolderSuggest extends AbstractInputSuggest<TFolder> {
|
||||
plugin: FolderNotesPlugin;
|
||||
|
||||
constructor(
|
||||
public inputEl: HTMLInputElement,
|
||||
plugin: FolderNotesPlugin,
|
||||
public inputEl: HTMLInputElement,
|
||||
plugin: FolderNotesPlugin,
|
||||
private whitelistSuggester: boolean,
|
||||
public folder?: TFolder,
|
||||
) {
|
||||
super(inputEl, plugin);
|
||||
super(plugin.app, inputEl);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,205 +0,0 @@
|
|||
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes and https://github.com/SilentVoid13/Templater
|
||||
|
||||
import { Scope, type ISuggestOwner } from 'obsidian';
|
||||
import { createPopper, type Instance as PopperInstance } from '@popperjs/core';
|
||||
import type FolderNotesPlugin from 'src/main';
|
||||
|
||||
const wrapAround = (value: number, size: number): number => {
|
||||
return ((value % size) + size) % size;
|
||||
};
|
||||
|
||||
class Suggest<T> {
|
||||
private owner: ISuggestOwner<T>;
|
||||
private values: T[];
|
||||
private suggestions: HTMLDivElement[];
|
||||
private selectedItem: number;
|
||||
private containerEl: HTMLElement;
|
||||
plugin: FolderNotesPlugin;
|
||||
|
||||
constructor(
|
||||
owner: ISuggestOwner<T>,
|
||||
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[]): void {
|
||||
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): void {
|
||||
const currentValue = this.values[this.selectedItem];
|
||||
if (currentValue) {
|
||||
this.owner.selectSuggestion(currentValue, event);
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedItem(selectedIndex: number, scrollIntoView: boolean): void {
|
||||
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<T> implements ISuggestOwner<T> {
|
||||
protected inputEl: HTMLInputElement | HTMLTextAreaElement;
|
||||
|
||||
private popper: PopperInstance;
|
||||
private scope: Scope;
|
||||
private suggestEl: HTMLElement;
|
||||
private suggest: Suggest<T>;
|
||||
plugin: FolderNotesPlugin;
|
||||
|
||||
constructor(inputEl: HTMLInputElement | HTMLTextAreaElement, plugin: FolderNotesPlugin) {
|
||||
this.inputEl = inputEl;
|
||||
this.plugin = plugin;
|
||||
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-expect-error App may not exist
|
||||
this.open(app.dom.appContainerEl, this.inputEl);
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
open(container: HTMLElement, inputEl: HTMLElement): void {
|
||||
|
||||
this.plugin.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 }): void => {
|
||||
// Note: positioning needs to be calculated twice -
|
||||
// first pass - positioning it according to the width of the popper
|
||||
// second pass - position it with the width bound to the reference element
|
||||
// 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 {
|
||||
this.plugin.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;
|
||||
}
|
||||
|
|
@ -47,13 +47,13 @@ export class TemplateSuggest extends AbstractInputSuggest<TFile> {
|
|||
{
|
||||
path: '',
|
||||
name:
|
||||
// eslint-disable-next-line max-len
|
||||
'You need to set the Templates folder in the Templater settings first.',
|
||||
// eslint-disable-next-line obsidianmd/no-tfile-tfolder-cast
|
||||
} as TFile,
|
||||
];
|
||||
}
|
||||
} else if (templateFolder) {
|
||||
folder = this.plugin.app.vault.getAbstractFileByPath(templateFolder) as TFolder;
|
||||
folder = this.plugin.app.vault.getAbstractFileByPath(templateFolder);
|
||||
}
|
||||
|
||||
if (!(folder instanceof TFolder)) {
|
||||
|
|
@ -86,7 +86,7 @@ export class TemplateSuggest extends AbstractInputSuggest<TFile> {
|
|||
this.inputEl.value = file.name.replace('.md', '');
|
||||
this.inputEl.trigger('input');
|
||||
this.plugin.settings.templatePath = file.path;
|
||||
this.plugin.saveSettings();
|
||||
void this.plugin.saveSettings();
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export async function applyTemplate(
|
|||
} = getTemplatePlugins(plugin.app);
|
||||
const templateContent = await plugin.app.vault.read(templateFile);
|
||||
// eslint-disable-next-line max-len
|
||||
if (templateContent.includes('==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠==')) {
|
||||
if (templateContent.includes('==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this activeDocument. ⚠==')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@
|
|||
}
|
||||
|
||||
|
||||
.fn-warning-text {
|
||||
color: #fb464c
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tree Items
|
||||
========================================================================== */
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"module": "node16",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "node16",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
|
|
@ -17,7 +17,10 @@
|
|||
"ES6",
|
||||
"ES7",
|
||||
"ES2021"
|
||||
]
|
||||
],
|
||||
"paths": {
|
||||
"@app/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable no-undef */
|
||||
import { readFileSync, writeFileSync } from "fs";
|
||||
|
||||
const targetVersion = process.env.npm_package_version;
|
||||
|
|
|
|||
Loading…
Reference in a new issue