feat: inject the data-path into .tree-item.nav-folder to avoid using :has selector.

Improve the perf on large vault
This commit is contained in:
Mara 2025-06-28 21:21:51 +02:00
parent 0610f5c9af
commit 34b57eb173
4 changed files with 56 additions and 10 deletions

View file

@ -29,11 +29,10 @@ Automagically add color to roots folders, and customize them with Style Settings
## 🎨 Configuration
In the plugin settings, you can customize :
- Export to a css snippets (instead of inject into the DOM)
- Export to a css snippets (instead of inject into the DOM)[^1]
- Default colors (when creating new folders)
- Folder name prefix for CSS varaible
- Custom CSS templates
- Custom style settings template
- Folder name prefix for CSS variable
- Custom CSS and Style Settings templates
![settings](./docs/assets/plugin_settings.png)
@ -66,3 +65,4 @@ To add a translation:
- Add `import * as <lang> from "./locales/<lang>.json";`
- Edit the `ressource` part with adding : `<lang> : {translation: <lang>}`
[^1]: Some styles can be broken while disabling the plugin, as it injects the folder path into `tree-item.nav-folder` to improve performance, instead to use `:has`.

View file

@ -16,6 +16,7 @@ import { convertStyleSettings, convertToCSS, generateName, themes } from "./temp
import { formatCss, removeExtraNewLine } from "./utils";
import dedent from "dedent";
import i18next from "i18next";
import type { DeferredView, FileExplorerView, MaybeDeferredView } from "obsidian-typings";
export class ColorCompiler {
plugin: SimpleColoredFolder;
@ -135,12 +136,50 @@ export class ColorCompiler {
return "";
}
async injectStyles(reload = true) {
const folders = this.app.vault
getFolder() {
return this.app.vault
.getAllFolders()
.filter(
(folder: TFolder) => folder.parent && folder.parent === this.app.vault.getRoot()
);
}
private getFileExplorerView() {
const navigation = this.app.workspace.getLeavesOfType("file-explorer");
if (navigation.length === 0) return null;
return navigation[0].view;
}
injectDataPathFromFolder(folder: TFolder, fileExplorer = this.getFileExplorerView()) {
const navigation = this.app.workspace.getLeavesOfType("file-explorer");
if (!navigation.length) return;
if (!fileExplorer) return;
const treeItems = fileExplorer.containerEl.querySelectorAll(
`.tree-item.nav-folder > .nav-folder-title[data-path="${folder.path}"]`
);
if (treeItems.length === 0) return;
treeItems.forEach((item) => {
const treeItem = item.closest(".tree-item.nav-folder");
if (treeItem) treeItem.setAttribute("data-path", folder.path);
});
}
/**
* Inject the data-path into the .tree-item.nav-folder
*/
injectDataPath(folders: TFolder[] = this.getFolder()) {
const navigation = this.app.workspace.getLeavesOfType("file-explorer");
if (!navigation.length) return;
const fileExplorer = navigation[0].view;
for (const folder of folders) {
this.injectDataPathFromFolder(folder, fileExplorer);
}
}
async injectStyles(reload = true, folders?: TFolder[]) {
if (!folders) folders = this.getFolder();
this.style?.detach();
const exportToCSS = this.settings.exportToCSS;
const style = this.createStyles(folders, !exportToCSS);

View file

@ -1,5 +1,5 @@
import i18next from "i18next";
import { Plugin, Notice, sanitizeHTMLToDom, normalizePath } from "obsidian";
import { Plugin, Notice, sanitizeHTMLToDom, normalizePath, TFolder } from "obsidian";
import { resources, translationLanguage } from "./i18n";
import { DEFAULT_SETTINGS, type SimpleColoredFolderSettings } from "./interfaces";
@ -34,11 +34,13 @@ export default class SimpleColoredFolder extends Plugin {
this.registerEvent(
this.app.vault.on("rename", async (file, oldPath) => {
await this.compiler.renameCss(file, oldPath);
if (file instanceof TFolder && file.parent === this.app.vault.getRoot())
this.compiler.injectDataPathFromFolder(file);
})
);
this.registerEvent(
this.app.vault.on("delete", async (file) => {
this.app.vault.on("delete", async () => {
await this.compiler.injectStyles();
})
);
@ -52,9 +54,14 @@ export default class SimpleColoredFolder extends Plugin {
)
);
}
await this.compiler.injectStyles(true);
const folders = this.compiler.getFolder();
this.compiler.injectDataPath(folders);
await this.compiler.injectStyles(true, folders);
this.app.vault.on("create", async (file) => {
await this.compiler.injectToRoot(file);
if (file instanceof TFolder && file.parent === this.app.vault.getRoot()) {
await this.compiler.injectDataPathFromFolder(file);
}
});
});
}

View file

@ -32,7 +32,7 @@ export function convertToCSS(folderName: string, prefix: Prefix, template: strin
color: var(${variableNames.color}) !important;
}
.tree-item.nav-folder:has([data-path="${folderName}"]) {
.tree-item.nav-folder[data-path="${folderName}"] {
background-color: var(${variableNames.bg}) !important;
border-radius: var(--spf-FolderRadius);
}