lostpaul_obsidian-folder-notes/src/Commands.ts

424 lines
15 KiB
TypeScript
Raw Normal View History

2023-08-10 19:54:22 +00:00
import { App, TFolder, Menu, TAbstractFile, Notice, TFile, Editor, MarkdownView, Platform, stringifyYaml } from 'obsidian';
2023-03-15 20:02:00 +00:00
import FolderNotesPlugin from './main';
2023-07-04 20:02:03 +00:00
import { getFolderNote, createFolderNote, deleteFolderNote, turnIntoFolderNote, openFolderNote, extractFolderName } from './functions/folderNoteFunctions';
import { ExcludedFolder } from './ExcludeFolders/ExcludeFolder';
import { getFolderPathFromString } from './functions/utils';
2023-03-15 20:02:00 +00:00
export class Commands {
2023-03-19 22:11:00 +00:00
plugin: FolderNotesPlugin;
app: App;
constructor(app: App, plugin: FolderNotesPlugin) {
this.plugin = plugin;
this.app = app;
}
registerCommands() {
2023-08-10 19:54:22 +00:00
this.editorCommands();
this.fileCommands();
this.regularCommands();
}
regularCommands() {
this.plugin.addCommand({
id: 'turn-into-folder-note',
name: 'Make current active note a folder note for the folder of the active note',
2023-08-10 19:54:22 +00:00
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof TFile)) return;
const folder = file.parent;
if (!(folder instanceof TFolder)) return;
const folderNote = getFolderNote(this.plugin, folder.path);
turnIntoFolderNote(this.plugin, file, folder, folderNote);
}
});
this.plugin.addCommand({
id: 'create-folder-note',
name: 'Create folder note with a new folder for the active note in the current folder',
callback: async () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof TFile)) return;
let newPath = file.parent?.path + '/' + file.basename;
if (file.parent?.path === '' || file.parent?.path === '/') {
newPath = file.basename;
}
if (this.plugin.app.vault.getAbstractFileByPath(newPath)) {
return new Notice('Folder already exists');
}
2023-11-02 16:56:57 +00:00
const automaticallyCreateFolderNote = this.plugin.settings.autoCreate;
this.plugin.settings.autoCreate = false;
this.plugin.saveSettings();
await this.plugin.app.vault.createFolder(newPath);
const folder = this.plugin.app.vault.getAbstractFileByPath(newPath);
if (!(folder instanceof TFolder)) return;
2023-11-02 16:56:57 +00:00
createFolderNote(this.plugin, folder.path, true, '.' + file.extension, false, file);
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
this.plugin.saveSettings();
}
})
this.plugin.addCommand({
id: 'create-folder-note-for-current-folder',
name: 'Create markdown folder note for current folder of active note',
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof TFile)) return;
const folder = file.parent;
if (!(folder instanceof TFolder)) return;
createFolderNote(this.plugin, folder.path, true, '.md', false);
}
});
this.plugin.settings.supportedFileTypes.forEach((fileType) => {
if (fileType === 'md') return;
this.plugin.addCommand({
id: `create-${fileType}-folder-note-for-current-folder`,
name: `Create ${fileType} folder note for current folder of active note`,
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof TFile)) return;
const folder = file.parent;
if (!(folder instanceof TFolder)) return;
createFolderNote(this.plugin, folder.path, true, '.' + fileType, false);
}
});
});
this.plugin.addCommand({
id: 'delete-folder-note-for-current-folder',
name: 'Delete folder note of current folder of active note',
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof TFile)) return;
const folder = file.parent;
if (!(folder instanceof TFolder)) return;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof TFile)) return;
deleteFolderNote(this.plugin, folderNote, true);
}
});
this.plugin.addCommand({
id: 'open-folder-note-for-current-folder',
name: 'Open folder note of current folder of active note',
callback: () => {
const file = this.app.workspace.getActiveFile();
if (!(file instanceof TFile)) return;
const folder = file.parent;
if (!(folder instanceof TFolder)) return;
const folderNote = getFolderNote(this.plugin, folder.path);
if (!(folderNote instanceof TFile)) return;
openFolderNote(this.plugin, folderNote);
}
});
this.plugin.addCommand({
id: 'insert-folder-overview-fn',
name: 'Insert folder overview',
editorCheckCallback: (checking: boolean, editor: Editor) => {
const line = editor.getCursor().line;
const lineText = editor.getLine(line);
if (lineText.trim() === '' || lineText.trim() === '>') {
if (!checking) {
let json = Object.assign({}, this.plugin.settings.defaultOverview);
json.id = crypto.randomUUID();
const yaml = stringifyYaml(json)
if (lineText.trim() === '') {
editor.replaceSelection(`\`\`\`folder-overview\n${yaml}\`\`\`\n`);
} else if (lineText.trim() === '>') {
// add > to the beginning of each line
const lines = yaml.split('\n');
const newLines = lines.map((line) => {
return `> ${line}`;
});
editor.replaceSelection(`\`\`\`folder-overview\n${newLines.join('\n')}\`\`\`\n`);
}
}
return true;
}
return false;
},
})
this.plugin.addCommand({
id: 'create-folder-note-from-selected-text',
name: 'Create folder note from selected text',
editorCheckCallback: (checking: boolean, editor: Editor, view: MarkdownView) => {
const text = editor.getSelection().trim();
const line = editor.getCursor().line;
const file = view.file;
if (!(file instanceof TFile)) return false;
if (text && text.trim() !== '') {
2023-11-02 16:56:57 +00:00
if (checking) { return true; }
const blacklist = ['*', '\\', '"', '/', '<', '>', '?', '|', ':'];
for (const char of blacklist) {
if (text.includes(char)) {
new Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
return false;
}
}
if (text.endsWith('.')) {
new Notice('File name cannot end with a dot');
return;
}
let folder: TAbstractFile | null;
const folderPath = getFolderPathFromString(file.path);
if (folderPath === '') {
folder = this.plugin.app.vault.getAbstractFileByPath(text);
if (folder instanceof TFolder) {
new Notice('Folder note already exists');
return false;
} else {
this.plugin.app.vault.createFolder(text);
createFolderNote(this.plugin, text, false);
}
} else {
folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + '/' + text);
if (folder instanceof TFolder) {
new Notice('Folder note already exists');
return false;
}
if (this.plugin.settings.storageLocation === 'parentFolder') {
if (this.app.vault.getAbstractFileByPath(folderPath + '/' + text + this.plugin.settings.folderNoteType)) {
new Notice('File already exists');
return false;
}
}
this.plugin.app.vault.createFolder(folderPath + '/' + text);
createFolderNote(this.plugin, folderPath + '/' + text, false);
}
const fileName = this.plugin.settings.folderNoteName.replace('{{folder_name}}', text);
if (fileName !== text) {
editor.replaceSelection(`[[${fileName}]]`);
} else {
editor.replaceSelection(`[[${fileName}|${text}]]`);
}
return true;
}
return false;
},
})
2023-08-10 19:54:22 +00:00
}
2023-08-10 19:54:22 +00:00
fileCommands() {
2023-03-19 22:11:00 +00:00
this.plugin.registerEvent(this.app.workspace.on('file-menu', (menu: Menu, file: TAbstractFile) => {
let folder: TAbstractFile | TFolder | null = file.parent;
if (file instanceof TFile) {
if (this.plugin.settings.storageLocation === 'insideFolder') {
folder = file.parent;
} else {
const fileName = extractFolderName(this.plugin.settings.folderNoteName, file.basename);
if (fileName) {
if (file.parent?.path === '' || file.parent?.path === '/') {
folder = this.plugin.app.vault.getAbstractFileByPath(fileName);
} else {
folder = this.plugin.app.vault.getAbstractFileByPath(file.parent?.path + '/' + fileName);
}
}
}
if (folder instanceof TFolder) {
const folderNote = getFolderNote(this.plugin, folder.path);
if (folderNote?.path === file.path) { return; }
} else if (file.parent instanceof TFolder) {
folder = file.parent;
}
}
menu.addItem((item) => {
2023-07-04 20:02:03 +00:00
if (Platform.isDesktop && !Platform.isTablet && this.plugin.settings.useSubmenus) {
item
.setTitle('Folder Note Commands')
.setIcon('folder-edit');
}
let subMenu: Menu;
2023-07-04 20:02:03 +00:00
if (!Platform.isDesktopApp || !Platform.isDesktop || Platform.isTablet || !this.plugin.settings.useSubmenus) {
subMenu = menu;
item.setDisabled(true);
} else {
// @ts-ignore
subMenu = item.setSubmenu() as Menu;
}
if (file instanceof TFile) {
// @ts-ignore
subMenu.addItem((item) => {
item.setTitle('Create folder note')
.setIcon('edit')
.onClick(async () => {
if (!folder) return;
let newPath = folder.path + '/' + file.basename;
if (folder.path === '' || folder.path === '/') {
newPath = file.basename;
}
if (this.plugin.app.vault.getAbstractFileByPath(newPath)) {
return new Notice('Folder already exists');
}
const automaticallyCreateFolderNote = this.plugin.settings.autoCreate;
this.plugin.settings.autoCreate = false;
this.plugin.saveSettings();
await this.plugin.app.vault.createFolder(newPath);
const newFolder = this.plugin.app.vault.getAbstractFileByPath(newPath);
if (!(newFolder instanceof TFolder)) return;
await createFolderNote(this.plugin, newFolder.path, true, '.' + file.extension, false, file);
this.plugin.settings.autoCreate = automaticallyCreateFolderNote;
this.plugin.saveSettings();
});
});
if (getFolderPathFromString(file.path) === '') return;
if (!(folder instanceof TFolder)) return;
subMenu.addItem((item) => {
item.setTitle(`Turn into folder note for ${folder?.name}`)
.setIcon('edit')
.onClick(() => {
if (!folder || !(folder instanceof TFolder)) return;
const folderNote = getFolderNote(this.plugin, folder.path);
turnIntoFolderNote(this.plugin, file, folder, folderNote);
});
});
}
if (!(file instanceof TFolder)) return;
if (this.plugin.settings.excludeFolders.find((folder) => folder.path === file.path)) {
subMenu.addItem((item) => {
item.setTitle('Remove folder from excluded folders')
.setIcon('trash')
.onClick(() => {
this.plugin.settings.excludeFolders = this.plugin.settings.excludeFolders.filter(
(folder) => folder.path !== file.path);
this.plugin.saveSettings();
new Notice('Successfully removed folder from excluded folders');
});
});
return;
}
subMenu.addItem((item) => {
item.setTitle('Exclude folder from folder notes')
.setIcon('x-circle')
2023-03-19 22:11:00 +00:00
.onClick(() => {
const excludedFolder = new ExcludedFolder(file.path, this.plugin.settings.excludeFolders.length, this.plugin);
this.plugin.settings.excludeFolders.push(excludedFolder);
2023-03-19 22:11:00 +00:00
this.plugin.saveSettings();
new Notice('Successfully excluded folder from folder notes');
2023-03-19 22:11:00 +00:00
});
});
if (!(file instanceof TFolder)) return;
const folderNote = getFolderNote(this.plugin, file.path);
if (folderNote instanceof TFile) {
subMenu.addItem((item) => {
item.setTitle('Delete folder note')
.setIcon('trash')
.onClick(() => {
deleteFolderNote(this.plugin, folderNote, true);
});
});
subMenu.addItem((item) => {
item.setTitle('Open folder note')
.setIcon('chevron-right-square')
.onClick(() => {
openFolderNote(this.plugin, folderNote);
});
});
2024-01-13 20:18:32 +00:00
subMenu.addItem((item) => {
item.setTitle('Copy Obsidian URL')
.setIcon('link')
.onClick(() => {
// @ts-ignore
this.app.copyObsidianUrl(folderNote);
});
});
} else {
subMenu.addItem((item) => {
item.setTitle('Create markdown folder note')
.setIcon('edit')
.onClick(() => {
createFolderNote(this.plugin, file.path, true, '.md');
});
2023-03-19 22:11:00 +00:00
});
this.plugin.settings.supportedFileTypes.forEach((fileType) => {
if (fileType === 'md') return;
subMenu.addItem((item) => {
item.setTitle(`Create ${fileType} folder note`)
.setIcon('edit')
.onClick(() => {
createFolderNote(this.plugin, file.path, true, '.' + fileType);
});
});
});
}
2023-03-19 22:11:00 +00:00
});
}));
}
2023-08-10 19:54:22 +00:00
editorCommands() {
this.plugin.registerEvent(this.plugin.app.workspace.on('editor-menu', (menu: Menu, editor: Editor, view: MarkdownView) => {
const text = editor.getSelection().trim();
const line = editor.getCursor().line;
const lineText = editor.getLine(line);
if (lineText.trim() === '' || lineText.trim() === '>') {
2023-08-10 19:54:22 +00:00
menu.addItem((item) => {
item.setTitle('Create folder overview')
.setIcon('edit')
.onClick(() => {
let json = Object.assign({}, this.plugin.settings.defaultOverview);
json.id = crypto.randomUUID();
const yaml = stringifyYaml(json)
if (lineText.trim() === '') {
editor.replaceSelection(`\`\`\`folder-overview\n${yaml}\`\`\`\n`);
} else if (lineText.trim() === '>') {
// add > to the beginning of each line
const lines = yaml.split('\n');
const newLines = lines.map((line) => {
return `> ${line}`;
});
editor.replaceSelection(`\`\`\`folder-overview\n${newLines.join('\n')}\`\`\`\n`);
}
2023-08-10 19:54:22 +00:00
});
});
}
if (!text || text.trim() === '') return;
menu.addItem((item) => {
item.setTitle('Create folder note')
.setIcon('edit')
.onClick(() => {
const file = view.file;
if (!(file instanceof TFile)) return;
const blacklist = ['*', '\\', '"', '/', '<', '>', '?', '|', ':'];
for (const char of blacklist) {
if (text.includes(char)) {
new Notice('File name cannot contain any of the following characters: * " \\ / < > : | ?');
return;
}
}
if (text.endsWith('.')) {
new Notice('File name cannot end with a dot');
return;
}
let folder: TAbstractFile | null;
const folderPath = getFolderPathFromString(file.path);
const fileName = this.plugin.settings.folderNoteName.replace('{{folder_name}}', text);
2023-08-10 19:54:22 +00:00
if (folderPath === '') {
folder = this.plugin.app.vault.getAbstractFileByPath(text);
if (folder instanceof TFolder) {
return new Notice('Folder note already exists');
} else {
this.plugin.app.vault.createFolder(text);
createFolderNote(this.plugin, text, false);
}
} else {
folder = this.plugin.app.vault.getAbstractFileByPath(folderPath + '/' + text);
if (folder instanceof TFolder) {
return new Notice('Folder note already exists');
}
if (this.plugin.settings.storageLocation === 'parentFolder') {
if (this.app.vault.getAbstractFileByPath(folderPath + '/' + fileName + this.plugin.settings.folderNoteType)) {
2023-08-10 19:54:22 +00:00
return new Notice('File already exists');
}
}
this.plugin.app.vault.createFolder(folderPath + '/' + text);
createFolderNote(this.plugin, folderPath + '/' + text, false);
}
if (fileName !== text) {
2023-08-10 19:54:22 +00:00
editor.replaceSelection(`[[${fileName}]]`);
} else {
editor.replaceSelection(`[[${fileName}|${text}]]`);
}
});
});
}));
}
2023-03-19 22:11:00 +00:00
}