diff --git a/Attribute-Garbage-Collector/Attribute-Garbage-Collector.zip b/Attribute-Garbage-Collector/Attribute-Garbage-Collector.zip deleted file mode 100644 index 68fe9eb..0000000 Binary files a/Attribute-Garbage-Collector/Attribute-Garbage-Collector.zip and /dev/null differ diff --git a/Attribute-Garbage-Collector/README.md b/Attribute-Garbage-Collector/README.md index b154e89..dbd9ba9 100644 --- a/Attribute-Garbage-Collector/README.md +++ b/Attribute-Garbage-Collector/README.md @@ -1,107 +1,103 @@ # Attribute GC — TriliumNext Maintenance Tool -A garbage collector for TriliumNext attributes. Scans all notes to find broken relations, unused labels, rare attributes, and near-duplicate names. Lets you preview them in a dashboard — with batch delete on classic Trilium. +Scans all notes in your TriliumNext database for broken relations, unused labels, rare attributes, and near-duplicate names. Preview and batch-delete them — **deletions persist**. -> **⚠ Status (TriliumNext)**: Detection works fully — all 83 notes, 66+ attribute groups scanned via `froca`. Deletion in the UI succeeds (cache is updated, re-scan confirms), but **changes are lost on page reload** because TriliumNext's frontend froca cache doesn't sync writes back to the server in the Render Note sandbox. Classic Trilium (`api.runOnBackend`) path works end-to-end. See [Persistence issue](#-persistence-issue-triliumnext). +> **v2.0** — Rewritten as a JS Frontend note with full `api.runOnBackend()` access. Scan and delete both work end-to-end on TriliumNext. The previous HTML Render Note approach (v1.x) could only detect — deletion did not persist. See [Why this works](#why-this-works). ## Features -- **Full scan** — Reads all notes via `froca` (TriliumNext) or `api.runOnBackend` (classic Trilium). Classifies every label and relation by usage count and health. -- **Broken relation detection** — Finds relations pointing to deleted or missing target notes. -- **Rare attribute flagging** — Highlights attributes used ≤2 times, plus temp/draft/test patterns. -- **Semantic duplicate finder** — Uses Levenshtein distance to surface near-identical names (`pipeline` vs `pipelne`, `autor` vs `autores`). +- **Full scan** — SQL-backed via `api.sql.getRows`. Classifies every label and relation by usage count and health. +- **Broken relation detection** — Relations pointing to deleted or missing target notes. +- **Rare attribute flagging** — Attributes used ≤2 times, plus temp/draft/test patterns. +- **Semantic duplicate finder** — Levenshtein distance to surface near-identical names (`pipeline` vs `pipelne`, `autor` vs `autores`). - **Dry run mode** — Toggle on to preview what would be deleted without making changes. -- **Batch selection** — Auto-select all problematic attributes with one click. -- **Scoped CSS** — All styles are prefixed under `#attrgc-root` — nothing leaks into the Trilium UI. +- **Batch deletion** — Auto-select all problematic attributes, then delete in one click. +- **Protected attributes** — 50+ system/internal labels and relations are locked from deletion. +- **Theme-aware** — Uses Trilium CSS variables, matches your theme automatically. ## Installation -1. In TriliumNext, import the .zip file (the plugin) into any root note of your choice (e.g., Tools, Plugins, or Add-ons). - -2. The import contains two notes: a Render note and an HTML code note. Simply click on the Render note to view the panel. +1. Create a **JS Frontend** code note in TriliumNext +2. Paste the full content of `attribute-gc.js` +3. Choose your mode: + - **Right panel widget**: add label `#widget`, reload (Ctrl+R), open any note + - **Full-page Render Note**: create a Render Note, add relation `~renderNote` → JS Frontend, open the Render Note ## Usage -1. Click **Escanear** — the tool reads all notes and shows a dashboard of attribute stats. -2. Use the filter tabs (**Quebrados**, **Raros**, **Sem uso**, **Sistema**) and search bar to narrow down. -3. Click **Auto-selecionar problemáticos** to check all non-system problematic attributes, or tick individual checkboxes. -4. **Toggle Dry Run OFF** (the yellow banner disappears). -5. Click **Executar limpeza** → confirm. The tool attempts to delete and runs a re-scan. +1. Click **Escanear** — stats dashboard appears with attribute counts +2. Filter by status (**Quebrados**, **Raros**, **Sem uso**, **Sistema**, **Saudáveis**) or search by name +3. Click **Auto-selecionar** to check all non-system problematic attributes, or tick individual rows +4. **Toggle Dry Run OFF** (yellow banner disappears) +5. Click **Executar limpeza** → confirm — attributes are permanently removed -> In classic Trilium, deletion persists to the database. In TriliumNext, the re-scan will show the attributes gone from the cache, but they reappear on reload (see below). +The individual **remover** button on each row works the same way (skips the batch dialog). ## Compatibility -| Environment | Scan | Delete | Notes | -|---|---|---|---| -| **Classic Trilium** | `api.sql.getRows` | `note.removeLabel` / `note.removeRelation` | Full end-to-end. | -| **TriliumNext** | `froca.notes` | `attr.update({ isDeleted: true })` | Detects everything. Delete works in UI but **not persisted**. | -| **Browser (demo)** | Mock data | Simulated (noop) | For testing outside Trilium. | +| Environment | Scan | Delete | +|---|---|---| +| **TriliumNext** | `api.sql.getRows` | `getNotesWithLabel` / `removeLabel` | +| **Classic Trilium** | `api.sql.getRows` | `getNotesWithLabel` / `removeLabel` | -## ⚠ Persistence issue (TriliumNext) +Both use the same backend path — `api.runOnBackend()` with the standard entity API. Becca stays in sync, changes persist. -### What works +## Why this works -- The froca path scans all 83 notes and 66+ attribute groups correctly. -- `note.getOwnedAttributes(type, name)` returns proper `FAttribute` objects. -- `attr.update({ isDeleted: true })` marks attributes deleted in the frontend cache. -- The re-scan confirms the deletions (groups count drops). -- `_clw.confirmSaveRelations()` exists and returns a Promise (talks to backend), but is scope-limited to the relations panel and doesn't propagate general attribute deletions. +v1.x used an **HTML Render Note** with inline `