Initial commit

This commit is contained in:
Lost Paul 2023-03-19 22:33:54 +01:00
parent e9380e5873
commit 8743474075
6 changed files with 115 additions and 47 deletions

View file

@ -1,5 +1,6 @@
import { App } from 'obsidian';
import { App, TFolder, Menu, TAbstractFile, Notice } from 'obsidian';
import FolderNotesPlugin from './main';
import { ExcludedFolder } from './settings';
export class Commands {
plugin: FolderNotesPlugin;
app: App;
@ -8,5 +9,30 @@ export class Commands {
this.app = app;
}
registerCommands() {
this.plugin.registerEvent(this.app.workspace.on('file-menu', (menu: Menu, file: TAbstractFile) => {
if (!(file instanceof TFolder)) return;
if (this.plugin.settings.excludeFolders.find((folder) => folder.path === file.path)) {
menu.addItem((item) => {
item.setTitle('Remove folder from excluded folders')
.setIcon('x')
.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;
}
menu.addItem((item) => {
item.setTitle('Exclude folder from folder notes')
.setIcon('x')
.onClick(() => {
const excludedFolder = new ExcludedFolder(file.path, this.plugin.settings.excludeFolders.length);
this.plugin.settings.excludeFolders.push(excludedFolder);
this.plugin.saveSettings();
new Notice('Successfully excluded folder from folder notes');
});
});
}));
}
}

View file

@ -1,7 +1,8 @@
import { Plugin, TFile, TFolder, TAbstractFile } from 'obsidian'
import { Plugin, TFile, TFolder, TAbstractFile, Notice } from 'obsidian'
import { DEFAULT_SETTINGS, FolderNotesSettings, SettingsTab } from './settings'
import FolderNameModal from './modals/folderName';
import { applyTemplate } from './template';
import { Commands } from './commands';
export default class FolderNotesPlugin extends Plugin {
observer: MutationObserver
folders: TFolder[] = []
@ -18,6 +19,7 @@ export default class FolderNotesPlugin extends Plugin {
} else {
document.body.classList.remove('hide-folder-note');
}
new Commands(this.app, this).registerCommands();
this.registerEvent(this.app.vault.on('create', (folder: TAbstractFile) => {
if (!this.app.workspace.layoutReady) return;
if (!this.settings.autoCreate) return;
@ -38,6 +40,7 @@ export default class FolderNotesPlugin extends Plugin {
}));
this.registerEvent(this.app.vault.on('rename', (file: TAbstractFile, oldPath: string) => {
console.log('rename')
if (!this.settings.syncFolderName) return;
if (file instanceof TFolder) {
const folder = this.app.vault.getAbstractFileByPath(file?.path);
@ -47,6 +50,23 @@ export default class FolderNotesPlugin extends Plugin {
(excludedFolder.path === folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length)
&& excludedFolder.subFolders));
if (excludedFolder?.disableSync) return;
const excludedFolders = this.settings.excludeFolders.filter(
(excludedFolder) => excludedFolder.path.includes(oldPath)
);
excludedFolders.forEach((excludedFolder) => {
const folders = excludedFolder.path.split('/');
if (folders.length < 1) {
folders.push(excludedFolder.path);
}
const oldName = oldPath.substring(oldPath.lastIndexOf('/' || '\\'));
console.log(oldName.replace('/', ''))
folders[folders.indexOf(oldName.replace('/', ''))] = folder.name;
excludedFolder.path = folders.join('/');
});
this.saveSettings();
const oldName = oldPath.substring(oldPath.lastIndexOf('/' || '\\'));
const newPath = folder?.path + '/' + folder?.name + '.md';
if (folder instanceof TFolder) {
@ -59,13 +79,26 @@ export default class FolderNotesPlugin extends Plugin {
}
} else if (file instanceof TFile) {
const folder = this.app.vault.getAbstractFileByPath(oldPath.substring(0, oldPath.lastIndexOf('/' || '\\')));
if (folder?.name + '.md' == file.name) return;
const oldFileName = oldPath.substring(oldPath.lastIndexOf('/' || '\\') + 1);
if (!folder) return;
const excludedFolder = this.settings.excludeFolders.find(
(excludedFolder) => (excludedFolder.path === folder.path) ||
(excludedFolder.path === folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length)
&& excludedFolder.subFolders));
if (excludedFolder?.disableSync) return;
if (file.name !== folder?.name + '.md') return;
if (oldFileName !== folder?.name + '.md') return console.log('not a folder note');
let newFolderPath = file.path.slice(0, file.path.lastIndexOf('/'))
if (newFolderPath.lastIndexOf('/') > 0) {
newFolderPath = newFolderPath.slice(0, newFolderPath.lastIndexOf('/')) + '/'
} else {
newFolderPath = ''
}
newFolderPath = newFolderPath + file.name.replace('.md', '');
if (this.app.vault.getAbstractFileByPath(newFolderPath)) {
this.app.vault.rename(file, oldPath);
return new Notice('A folder with the same name already exists');
}
if (folder instanceof TFolder) {
this.app.vault.rename(folder, folder.path.substring(0, folder.path.lastIndexOf('/' || '\\')) + '/' + file.name.substring(0, file.name.lastIndexOf('.')));
}
@ -109,7 +142,7 @@ export default class FolderNotesPlugin extends Plugin {
event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file')
.forEach((element: HTMLElement) => {
if (element.innerText === (event.target as HTMLElement)?.innerText && element.classList.contains('is-folder-note')) {
element.classList.remove('is-folder-note');
element.removeClass('is-folder-note');
}
});
return;
@ -125,8 +158,8 @@ export default class FolderNotesPlugin extends Plugin {
event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file')
.forEach((element: HTMLElement) => {
if (element.innerText === (event.target as HTMLElement)?.innerText && !element.classList.contains('is-folder-note')) {
console.log(element)
element.classList.add('is-folder-note');
element.addClass('is-folder-note');
}
});
@ -137,7 +170,7 @@ export default class FolderNotesPlugin extends Plugin {
event.target.parentElement?.parentElement?.getElementsByClassName('nav-folder-children').item(0)?.querySelectorAll('div.nav-file')
.forEach((element: HTMLElement) => {
if (element.innerText === (event.target as HTMLElement)?.innerText && !element.classList.contains('is-folder-note')) {
element.classList.add('is-folder-note');
element.addClass('is-folder-note');
}
});
} else {
@ -156,7 +189,9 @@ export default class FolderNotesPlugin extends Plugin {
if (openFile) {
await leaf.openFile(file);
}
applyTemplate(this, this.settings.templatePath);
if (file) {
applyTemplate(this, file, this.settings.templatePath);
}
if (!this.settings.autoCreate) return;
if (!useModal) return;
const folder = this.app.vault.getAbstractFileByPath(path.substring(0, path.lastIndexOf('/' || '\\')));

View file

@ -15,20 +15,25 @@ export default class ConfirmationModal extends Modal {
const setting = new Setting(contentEl)
setting.infoEl.createEl('p', { text: 'Make sure to backup your vault before using this feature.' }).style.color = '#fb464c';
setting.infoEl.createEl('p', { text: 'This feature will create a folder note for every folder in your vault.' });
setting.infoEl.createEl('p', { text: 'Every folder that already has a folder note will be ignored' });
setting.infoEl.createEl('p', { text: 'Every folder that already has a folder note will be ignored.' });
setting.infoEl.createEl('p', { text: 'Every excluded folder will be ignored.' });
setting.infoEl.parentElement?.classList.add('fn-confirmation-modal')
const button = setting.infoEl.createEl('button', { text: 'Create' });
button.classList.add('mod-warning', 'fn-confirmation-modal-button');
button.addEventListener('click', async () => {
this.close();
this.app.vault.getAllLoadedFiles().forEach(async (file) => {
if (file instanceof TFolder) {
if (this.app.vault.getAbstractFileByPath(file.path + '/' + file.name + '.md')) return;
await this.plugin.createFolderNote(file.path + '/' + file.name + '.md', false);
this.app.vault.getAllLoadedFiles().forEach(async (folder) => {
if (folder instanceof TFolder) {
const excludedFolder = this.plugin.settings.excludeFolders.find(
(excludedFolder) => (excludedFolder.path === folder.path) ||
(excludedFolder.path === folder.path?.slice(0, folder?.path.lastIndexOf("/") >= 0 ? folder.path?.lastIndexOf("/") : folder.path.length)
&& excludedFolder.subFolders));
if (excludedFolder) return;
if (this.app.vault.getAbstractFileByPath(folder.path + '/' + folder.name + '.md')) return;
await this.plugin.createFolderNote(folder.path + '/' + folder.name + '.md', true);
}
})
});
// focus on the button
button.focus();
const cancelButton = setting.infoEl.createEl('button', { text: 'Cancel' });
cancelButton.addEventListener('click', async () => {

View file

@ -12,6 +12,12 @@ export default class FolderNameModal extends Modal {
}
onOpen() {
const { contentEl } = this;
// close when user presses enter
contentEl.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
this.close();
}
});
contentEl.createEl('h2', { text: 'Folder name' });
new Setting(contentEl)
.setName('Enter the name of the folder')
@ -20,7 +26,10 @@ export default class FolderNameModal extends Modal {
.setValue(this.folder.name.replace('.md', ''))
.onChange(async (value) => {
if (value.trim() !== "") {
this.app.vault.rename(this.folder, this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + value);
if (!this.app.vault.getAbstractFileByPath(this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + value.trim()))
{
this.app.vault.rename(this.folder, this.folder.path.slice(0, this.folder.path.lastIndexOf('/') + 1) + value.trim());
}
}
})
);

View file

@ -3,7 +3,7 @@ import FolderNotesPlugin from "./main";
import { FolderSuggest } from "./suggesters/folderSuggester";
import ExcludedFolderSettings from "./modals/exludeFolderSettings";
import { TemplateSuggest } from "./suggesters/templateSuggester";
import ConfirmationModal from "./modals/confirmCreation";
//import ConfirmationModal from "./modals/confirmCreation";
export interface FolderNotesSettings {
syncFolderName: boolean;
ctrlKey: boolean;
@ -19,7 +19,7 @@ export const DEFAULT_SETTINGS: FolderNotesSettings = {
syncFolderName: true,
ctrlKey: true,
altKey: false,
hideFolderNote: true,
hideFolderNote: false,
templatePath: '',
autoCreate: false,
enableCollapsing: false,
@ -125,18 +125,22 @@ export class SettingsTab extends PluginSettingTab {
});
});
new Setting(containerEl)
.setName('Create folder note for every folder')
.setDesc('Create a folder note for every folder in the vault')
.addButton((cb) => {
cb.setIcon('plus');
// Due to issue with templater it'll be disabled for now
// If you want to try it yourself make a pr
// The issue was that it only used the first folder for all of the other folder notes
/*
new Setting(containerEl)
.setName('Create folder note for every folder')
.setDesc('Create a folder note for every folder in the vault')
.addButton((cb) => {
cb.setIcon('plus');
cb.setTooltip('Create folder notes');
cb.onClick(async () => {
new ConfirmationModal(this.app, this.plugin).open();
});
cb.setTooltip('Create folder notes');
cb.onClick(async () => {
new ConfirmationModal(this.app, this.plugin).open();
});
});
*/
new Setting(containerEl)
@ -191,7 +195,6 @@ export class SettingsTab extends PluginSettingTab {
cb.onClick(() => {
if (excludedFolder.position === 0) return;
excludedFolder.position = excludedFolder.position - 1;
console.log(excludedFolder.position);
this.updateExcludedFolder(excludedFolder, excludedFolder);
const oldExcludedFolder = this.plugin.settings.excludeFolders.find(folder => folder.position == excludedFolder.position)
if (oldExcludedFolder) {

View file

@ -2,10 +2,11 @@
// from where I got the template code for this plugin
// https://github.com/mgmeyers/obsidian-kanban/blob/48e6c278ce9140b7e034b181432321f697d6e45e/src/components/helpers.ts
import { TFile, MarkdownView, App } from 'obsidian';
import { TFile, App } from 'obsidian';
import FolderNotesPlugin from './main';
export async function applyTemplate(
plugin: FolderNotesPlugin,
file: TFile,
templatePath?: string
) {
const templateFile = templatePath
@ -13,19 +14,7 @@ export async function applyTemplate(
: null;
if (templateFile && templateFile instanceof TFile) {
const activeView = app.workspace.getActiveViewOfType(MarkdownView);
try {
// Force the view to source mode, if needed
if (activeView?.getMode() !== 'source') {
await activeView?.setState(
{
...activeView.getState(),
mode: 'source',
},
{}
);
}
const {
templatesEnabled,
@ -33,17 +22,17 @@ export async function applyTemplate(
templatesPlugin,
templaterPlugin,
} = getTemplatePlugins(plugin.app);
const templateContent = await plugin.app.vault.read(templateFile);
// If both plugins are enabled, attempt to detect templater first
if (templatesEnabled && templaterEnabled) {
if (/<%/.test(templateContent)) {
return await templaterPlugin.append_template_to_active_file(
templateFile
return await templaterPlugin.write_template_to_file(
templateFile,
file
);
}
return await templatesPlugin.instance.insertTemplate(templateFile);
}
@ -52,8 +41,9 @@ export async function applyTemplate(
}
if (templaterEnabled) {
return await templaterPlugin.append_template_to_active_file(
templateFile
return await templaterPlugin.write_template_to_file(
templateFile,
file
);
}