2023-06-26 11:14:31 +00:00
|
|
|
import { MarkdownPostProcessorContext, parseYaml, TAbstractFile, TFolder, TFile } from 'obsidian';
|
2023-06-28 21:01:13 +00:00
|
|
|
import { getFolderNote } from './functions/folderNoteFunctions';
|
2023-06-26 11:14:31 +00:00
|
|
|
import FolderNotesPlugin from './main';
|
2023-06-28 21:01:13 +00:00
|
|
|
export type yamlSettings = {
|
|
|
|
|
title?: string;
|
|
|
|
|
disableTitle?: boolean;
|
|
|
|
|
depth?: number;
|
|
|
|
|
type?: 'folder' | 'markdown' | 'canvas';
|
|
|
|
|
includeTypes?: string[];
|
|
|
|
|
style?: 'list' | 'grid';
|
|
|
|
|
disableCanvasTag?: boolean;
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-26 11:14:31 +00:00
|
|
|
export function createCanvasOverview() {
|
|
|
|
|
// console.log('test');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function createOverview(plugin: FolderNotesPlugin, source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) {
|
|
|
|
|
// parse source to yaml
|
|
|
|
|
const yaml = parseYaml(source);
|
|
|
|
|
const depth = yaml?.depth || 1;
|
2023-06-28 21:01:13 +00:00
|
|
|
const title = yaml?.title || plugin.settings.defaultOverview.title || 'Folder overview';
|
|
|
|
|
const disableTitle = yaml?.disableTitle || plugin.settings.defaultOverview.disableTitle || false;
|
|
|
|
|
let includeTypes: string[] = yaml?.includeTypes || plugin.settings.defaultOverview.includeTypes || ['folder', 'markdown'];
|
|
|
|
|
includeTypes = includeTypes.map((type) => type.toLowerCase());
|
|
|
|
|
const style: 'list' | 'grid' = yaml?.style || 'list';
|
|
|
|
|
const disableCanvasTag = yaml?.disableCanvasTag || plugin.settings.defaultOverview.disableCanvasTag || false;
|
|
|
|
|
|
|
|
|
|
const root = el.createEl('div', { cls: 'folder-overview' });
|
|
|
|
|
const titleEl = root.createEl('h1', { cls: 'folder-overview-title' });
|
|
|
|
|
const ul = root.createEl('ul', { cls: 'folder-overview-list' });
|
|
|
|
|
if (!disableTitle) {
|
|
|
|
|
titleEl.innerText = title;
|
|
|
|
|
}
|
|
|
|
|
if (includeTypes.length === 0) { return; }
|
2023-06-26 11:14:31 +00:00
|
|
|
let files: TAbstractFile[] = [];
|
|
|
|
|
const sourceFile = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
|
|
|
|
|
if (!sourceFile) return;
|
|
|
|
|
const sourceFolderPath = plugin.getFolderPathFromString(ctx.sourcePath);
|
|
|
|
|
let sourceFolder: TFolder | undefined;
|
|
|
|
|
|
|
|
|
|
if (sourceFile.parent instanceof TFolder) {
|
|
|
|
|
sourceFolder = sourceFile.parent;
|
|
|
|
|
} else {
|
|
|
|
|
sourceFolder = plugin.app.vault.getAbstractFileByPath(plugin.getFolderPathFromString(ctx.sourcePath)) as TFolder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
files = sourceFolder.children;
|
|
|
|
|
|
|
|
|
|
files = files.filter((file) => {
|
|
|
|
|
const folderPath = plugin.getFolderPathFromString(file.path);
|
|
|
|
|
if (!folderPath.startsWith(sourceFolderPath)) { return false; }
|
|
|
|
|
if (file.path === ctx.sourcePath) { return false; }
|
|
|
|
|
if ((file.path.split('/').length - sourceFolderPath.split('/').length) - 1 < depth) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-06-28 21:01:13 +00:00
|
|
|
if (!includeTypes.includes('folder')) {
|
|
|
|
|
files = getAllFiles(files, sourceFolderPath, depth);
|
|
|
|
|
}
|
2023-06-26 11:14:31 +00:00
|
|
|
files = sortFiles(files);
|
|
|
|
|
|
|
|
|
|
if (style === 'grid') {
|
|
|
|
|
const grid = root.createEl('div', { cls: 'folder-overview-grid' });
|
|
|
|
|
files.forEach((file) => {
|
|
|
|
|
const gridItem = grid.createEl('div', { cls: 'folder-overview-grid-item' });
|
|
|
|
|
const link = gridItem.createEl('a', { cls: 'folder-overview-grid-item-link' });
|
|
|
|
|
link.innerText = file.name.replace('.md', '').replace('.canvas', '');
|
|
|
|
|
if (!(file instanceof TFile)) return;
|
|
|
|
|
link.href = plugin.app.fileManager.generateMarkdownLink(file, '', ctx.sourcePath);
|
|
|
|
|
});
|
|
|
|
|
} else if (style === 'list') {
|
|
|
|
|
const pathBlacklist: string[] = [];
|
|
|
|
|
files.forEach((file) => {
|
|
|
|
|
if (file instanceof TFolder) {
|
2023-06-28 21:01:13 +00:00
|
|
|
const folderItem = addFolderList(plugin, ul, pathBlacklist, file);
|
|
|
|
|
goThroughFolders(plugin, folderItem, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableCanvasTag);
|
2023-06-26 11:14:31 +00:00
|
|
|
} else if (file instanceof TFile) {
|
2023-06-28 21:01:13 +00:00
|
|
|
addFileList(plugin, ul, pathBlacklist, file, includeTypes, disableCanvasTag);
|
2023-06-26 11:14:31 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (style === 'explorer') {
|
|
|
|
|
/*
|
|
|
|
|
const view = plugin.getFileExplorerView();
|
|
|
|
|
const folderElement = plugin.getEL(plugin.getFolderPathFromString(ctx.sourcePath))?.parentElement;
|
|
|
|
|
if (!folderElement) return;
|
|
|
|
|
// copy folderElement
|
|
|
|
|
const newFolderElement = folderElement.cloneNode(true) as HTMLElement;
|
|
|
|
|
newFolderElement.querySelectorAll('.nav-folder').forEach((el) => {
|
|
|
|
|
el.classList.remove('is-collapsed');
|
|
|
|
|
});
|
|
|
|
|
root.appendChild(folderElement);
|
|
|
|
|
*/
|
|
|
|
|
}
|
2023-06-28 21:01:13 +00:00
|
|
|
if (includeTypes.length > 1) {
|
|
|
|
|
removeEmptyFolders(ul);
|
|
|
|
|
}
|
2023-06-26 11:14:31 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-28 21:01:13 +00:00
|
|
|
function goThroughFolders(plugin: FolderNotesPlugin, list: HTMLLIElement | HTMLUListElement, folder: TFolder,
|
|
|
|
|
depth: number, sourceFolderPath: string, ctx: MarkdownPostProcessorContext, yaml: yamlSettings, pathBlacklist: string[], includeTypes: string[], disableCanvasTag: boolean) {
|
2023-06-26 11:14:31 +00:00
|
|
|
let files = folder.children.filter((file) => {
|
|
|
|
|
const folderPath = plugin.getFolderPathFromString(file.path);
|
|
|
|
|
if (!folderPath.startsWith(sourceFolderPath)) { return false; }
|
|
|
|
|
if ((file.path.split('/').length - sourceFolderPath.split('/').length) - 1 < depth) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
files = sortFiles(files);
|
|
|
|
|
const ul = list.createEl('ul', { cls: 'folder-overview-list' });
|
|
|
|
|
files.forEach((file) => {
|
|
|
|
|
if (file instanceof TFolder) {
|
2023-06-28 21:01:13 +00:00
|
|
|
const folderItem = addFolderList(plugin, ul, pathBlacklist, file);
|
|
|
|
|
goThroughFolders(plugin, folderItem, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableCanvasTag);
|
2023-06-26 11:14:31 +00:00
|
|
|
} else if (file instanceof TFile) {
|
2023-06-28 21:01:13 +00:00
|
|
|
addFileList(plugin, ul, pathBlacklist, file, includeTypes, disableCanvasTag);
|
2023-06-26 11:14:31 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function sortFiles(files: TAbstractFile[]) {
|
|
|
|
|
return files.sort((a, b) => {
|
|
|
|
|
// sort by folder first
|
|
|
|
|
if (a instanceof TFolder && !(b instanceof TFolder)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (!(a instanceof TFolder) && b instanceof TFolder) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
// sort by name
|
|
|
|
|
if (a.name < b.name) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (a.name > b.name) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function removeEmptyFolders(ul: HTMLUListElement | HTMLLIElement) {
|
|
|
|
|
const childrensToRemove: ChildNode[] = [];
|
|
|
|
|
ul.childNodes.forEach((el) => {
|
|
|
|
|
const childrens = (el as Element).querySelector('ul');
|
|
|
|
|
if (!childrens || childrens === null) { return; }
|
|
|
|
|
if (childrens && !childrens?.hasChildNodes() && !(el instanceof HTMLUListElement)) {
|
|
|
|
|
childrensToRemove.push(el);
|
|
|
|
|
} else if (el instanceof HTMLUListElement || el instanceof HTMLLIElement) {
|
|
|
|
|
removeEmptyFolders(el);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
childrensToRemove.forEach((el) => {
|
|
|
|
|
el.remove();
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-06-28 21:01:13 +00:00
|
|
|
|
|
|
|
|
function addFolderList(plugin: FolderNotesPlugin, list: HTMLUListElement | HTMLLIElement, pathBlacklist: string[], folder: TFolder) {
|
|
|
|
|
const folderItem = list.createEl('li', { cls: 'folder-overview-list folder-list' });
|
|
|
|
|
const folderNote = getFolderNote(plugin, folder.path);
|
|
|
|
|
if (folderNote instanceof TFile) {
|
|
|
|
|
const folderNoteLink = folderItem.createEl('a', { cls: 'folder-overview-list-item folder-name-item internal-link', href: folderNote.path });
|
|
|
|
|
folderNoteLink.innerText = folder.name;
|
|
|
|
|
pathBlacklist.push(folderNote.path);
|
|
|
|
|
} else {
|
|
|
|
|
const folderName = folderItem.createEl('span', { cls: 'folder-overview-list-item folder-name-item' });
|
|
|
|
|
folderName.innerText = folder.name;
|
|
|
|
|
}
|
|
|
|
|
return folderItem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addFileList(plugin: FolderNotesPlugin, list: HTMLUListElement | HTMLLIElement, pathBlacklist: string[], file: TFile, includeTypes: string[], disableCanvasTag: boolean) {
|
|
|
|
|
if (includeTypes.length > 0) {
|
|
|
|
|
if (file.extension === 'md' && !includeTypes.includes('markdown')) return;
|
|
|
|
|
if (file.extension === 'canvas' && !includeTypes.includes('canvas')) return;
|
|
|
|
|
}
|
|
|
|
|
if (pathBlacklist.includes(file.path)) return;
|
|
|
|
|
const listItem = list.createEl('li', { cls: 'folder-overview-list file-link' });
|
|
|
|
|
const nameItem = listItem.createEl('div', { cls: 'folder-overview-list-item' });
|
|
|
|
|
const link = nameItem.createEl('a', { cls: 'internal-link', href: file.path });
|
|
|
|
|
link.innerText = file.name.replace('.md', '').replace('.canvas', '');
|
|
|
|
|
if (file.extension === 'canvas' && !disableCanvasTag) {
|
|
|
|
|
nameItem.createDiv({ cls: 'nav-file-tag' }).innerText = 'canvas';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getAllFiles(files: TAbstractFile[], sourceFolderPath: string, depth: number) {
|
|
|
|
|
const allFiles: TAbstractFile[] = [];
|
|
|
|
|
files.forEach((file) => {
|
|
|
|
|
if (file instanceof TFolder) {
|
|
|
|
|
if ((file.path.split('/').length - sourceFolderPath.split('/').length) - 1 < depth -1) {
|
|
|
|
|
allFiles.push(...getAllFiles(file.children, sourceFolderPath, depth));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
allFiles.push(file);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return allFiles;
|
|
|
|
|
}
|