mirror of
https://github.com/lostpaul/obsidian-folder-notes.git
synced 2026-07-22 07:40:24 +00:00
Merge 89bae42d0b into 494d159107
This commit is contained in:
commit
e6440ccc85
2 changed files with 131 additions and 0 deletions
128
src/api.ts
Normal file
128
src/api.ts
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
import { TFile, TFolder } from 'obsidian';
|
||||
import type FolderNotesPlugin from './main';
|
||||
import { getFolderNote, createFolderNote } from './functions/folderNoteFunctions';
|
||||
import { getDetachedFolder, getExcludedFolder } from './ExcludeFolders/functions/folderFunctions';
|
||||
|
||||
const API_VERSION = '1.0.0';
|
||||
|
||||
export interface ConvertNoteToFolderNoteOptions {
|
||||
skipConfirmation?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public API exposed by the folder-notes plugin on its instance as `plugin.api`.
|
||||
*
|
||||
* External plugins can access it via:
|
||||
* app.plugins.plugins['folder-notes']?.api
|
||||
*
|
||||
* The API is available after folder-notes has finished onload (settings loaded).
|
||||
*/
|
||||
export interface FolderNotesApi {
|
||||
/** Semver-ish version string for feature detection. */
|
||||
version: string;
|
||||
|
||||
/**
|
||||
* Returns the folder note TFile for the given folder path only if the
|
||||
* folder's note is enabled — i.e., the folder is not detached and not
|
||||
* excluded with `disableFolderNote`. Matches the plugin's own UI
|
||||
* gating (the rules that decide whether `.has-folder-note` gets
|
||||
* applied in the file explorer).
|
||||
*
|
||||
* Returns null if:
|
||||
* - the folder does not exist or has no folder note
|
||||
* - the folder is detached
|
||||
* - the folder is excluded with disableFolderNote
|
||||
*/
|
||||
getEnabledFolderNote(folderPath: string): TFile | null;
|
||||
|
||||
/**
|
||||
* Converts an existing note into the folder note for its parent folder.
|
||||
* Throws FolderNotesApiPathError if the path does not point to a note
|
||||
* inside a non-root folder.
|
||||
* Throws FolderNotesApiAlreadyFolderNoteError if the note is already
|
||||
* a folder note (e.g. aa/aa.md).
|
||||
*/
|
||||
convertNoteToFolderNote(notePath: string, options?: ConvertNoteToFolderNoteOptions): Promise<void>;
|
||||
}
|
||||
|
||||
export class FolderNotesApiPathError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
readonly notePath: string,
|
||||
) {
|
||||
super(message);
|
||||
this.name = 'FolderNotesApiPathError';
|
||||
}
|
||||
}
|
||||
|
||||
export class FolderNotesApiAlreadyFolderNoteError extends Error {
|
||||
constructor(readonly notePath: string) {
|
||||
super(`Note is already a folder note: ${notePath}`);
|
||||
this.name = 'FolderNotesApiAlreadyFolderNoteError';
|
||||
}
|
||||
}
|
||||
|
||||
export function getApi(plugin: FolderNotesPlugin): FolderNotesApi {
|
||||
return {
|
||||
version: API_VERSION,
|
||||
getEnabledFolderNote: (folderPath) => getEnabledFolderNote(plugin, folderPath),
|
||||
convertNoteToFolderNote: (notePath, options) => convertNoteToFolderNote(plugin, notePath, options),
|
||||
};
|
||||
}
|
||||
|
||||
function getEnabledFolderNote(plugin: FolderNotesPlugin, folderPath: string): TFile | null {
|
||||
const note = getFolderNote(plugin, folderPath);
|
||||
if (!note) return null;
|
||||
if (getDetachedFolder(plugin, folderPath)) return null;
|
||||
const excluded = getExcludedFolder(plugin, folderPath, true);
|
||||
if (excluded?.disableFolderNote) return null;
|
||||
return note;
|
||||
}
|
||||
|
||||
async function convertNoteToFolderNote(
|
||||
plugin: FolderNotesPlugin,
|
||||
notePath: string,
|
||||
options: ConvertNoteToFolderNoteOptions = {},
|
||||
): Promise<void> {
|
||||
const file = plugin.app.vault.getAbstractFileByPath(notePath);
|
||||
if (!(file instanceof TFile)) {
|
||||
throw new FolderNotesApiPathError(`No note exists at path: ${notePath}`, notePath);
|
||||
}
|
||||
|
||||
const parentFolder = file.parent;
|
||||
if (!(parentFolder instanceof TFolder) || parentFolder.path === '' || parentFolder.path === '/') {
|
||||
throw new FolderNotesApiPathError(`Note must be inside a non-root folder: ${notePath}`, notePath);
|
||||
}
|
||||
|
||||
// Guard: already a folder note (e.g. aa/aa.md)
|
||||
if (getFolderNote(plugin, parentFolder.path) === file) {
|
||||
throw new FolderNotesApiAlreadyFolderNoteError(notePath);
|
||||
}
|
||||
|
||||
// Build the new folder path: sibling folder named after the note's basename
|
||||
const newFolderPath = parentFolder.path === ''
|
||||
? file.basename
|
||||
: `${parentFolder.path}/${file.basename}`;
|
||||
|
||||
if (plugin.app.vault.getAbstractFileByPath(newFolderPath)) {
|
||||
throw new FolderNotesApiPathError(`A folder already exists at: ${newFolderPath}`, notePath);
|
||||
}
|
||||
|
||||
// Temporarily disable autoCreate to avoid the plugin auto-creating a folder note on folder creation
|
||||
const previousAutoCreate = plugin.settings.autoCreate;
|
||||
plugin.settings.autoCreate = false;
|
||||
void plugin.saveSettings();
|
||||
|
||||
await plugin.app.vault.createFolder(newFolderPath);
|
||||
const newFolder = plugin.app.vault.getAbstractFileByPath(newFolderPath);
|
||||
if (!(newFolder instanceof TFolder)) {
|
||||
plugin.settings.autoCreate = previousAutoCreate;
|
||||
void plugin.saveSettings();
|
||||
throw new FolderNotesApiPathError(`Failed to create folder at: ${newFolderPath}`, notePath);
|
||||
}
|
||||
|
||||
await createFolderNote(plugin, newFolder.path, false, '.' + file.extension, false, file);
|
||||
|
||||
plugin.settings.autoCreate = previousAutoCreate;
|
||||
void plugin.saveSettings();
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ import { registerOverviewCommands } from './obsidian-folder-overview/src/Command
|
|||
import { updateOverviewView, updateViewDropdown } from './obsidian-folder-overview/src/main';
|
||||
import { FvIndexDB } from './obsidian-folder-overview/src/utils/IndexDB';
|
||||
import { updateAllOverviews } from './obsidian-folder-overview/src/utils/functions';
|
||||
import { getApi, type FolderNotesApi } from './api';
|
||||
|
||||
interface FileExplorerPluginLike extends Plugin {
|
||||
revealInFolder: (file: TAbstractFile) => void;
|
||||
|
|
@ -88,6 +89,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
settingsOpened = false;
|
||||
askModalCurrentlyOpen = false;
|
||||
fvIndexDB!: FvIndexDB;
|
||||
api!: FolderNotesApi;
|
||||
|
||||
async onload(): Promise<void> {
|
||||
console.debug('loading folder notes plugin');
|
||||
|
|
@ -95,6 +97,7 @@ export default class FolderNotesPlugin extends Plugin {
|
|||
this.settingsTab = new SettingsTab(this.app, this);
|
||||
this.addSettingTab(this.settingsTab);
|
||||
await this.saveSettings();
|
||||
this.api = getApi(this);
|
||||
this.fvIndexDB = new FvIndexDB(this);
|
||||
|
||||
// Add CSS Classes
|
||||
|
|
|
|||
Loading…
Reference in a new issue