diff --git a/README.md b/README.md index 66f81b9..ff636a9 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,32 @@ # Table of Contents Generator -A modern Obsidian plugin that generates clean, trackable table of contents using frontmatter metadata. Creates invisible TOC markers without cluttering your source view, with advanced configuration options and automatic updates. +An Obsidian plugin that generates a table of contents from your note's headings — no visible HTML markers, tracked through a small YAML frontmatter key instead. ## Why This Plugin? -This plugin differs from other TOC solutions in several key ways: - -- **Frontmatter-Based Tracking**: Uses YAML frontmatter instead of HTML comments for TOC state management, keeping your source view clean and readable -- **No Visible Markers**: Unlike plugins that insert HTML comments (``) visible in source mode, this plugin's TOC tracking is completely invisible -- **Metadata Cache Integration**: Leverages Obsidian's built-in metadata cache system for efficient heading detection and frontmatter management -- **Smart Positioning**: Automatically places TOC at the document start or after the last H1 heading, intelligently adapting to your document structure -- **Duplicate Heading Support**: Correctly handles duplicate headings using Obsidian's native linking format with space separators -- **Security Hardened**: Includes ReDoS protection for user-provided regex patterns to prevent performance issues +- **No visible markers**: unlike plugins that insert HTML comments (``) into your source view, the TOC section is identified by its heading and tracked via frontmatter +- **Safe updates**: the TOC section is only ever matched by its heading title (your configured title or common ones like "Contents"), so regenerating never touches other sections of your note +- **Idempotent**: regenerating an unchanged note produces byte-identical content — safe to combine with sync and auto-formatting plugins +- **Wikilink navigation**: entries are `[[#Heading|Heading]]` links that work in preview and live preview Buy Me A Coffee ## Features -### Core Functionality -- **Invisible Markers**: No visible HTML comments - uses YAML frontmatter exclusively for TOC tracking -- **Smart Positioning**: Intelligent TOC placement at document start or after the last H1 heading -- **Automatic Updates**: Debounced auto-updates when document changes (configurable) -- **Clean Integration**: Works seamlessly with Obsidian's metadata cache system - -### Advanced Configuration -- **Heading Depth Control**: Exclude H1 headings and set maximum depth (1-6) -- **Pattern Exclusion**: Regex patterns to exclude specific headings (with ReDoS protection) -- **Link Options**: Toggle clickable TOC links to headings -- **Custom TOC Title**: Personalize your table of contents heading -- **Duplicate Handling**: Smart handling of duplicate heading names - -### Developer Features -- **Debug Command**: Built-in TOC marker debugging for troubleshooting -- **TypeScript Support**: Full type safety with comprehensive interfaces -- **Service Architecture**: Clean separation of concerns with dedicated service classes +- **Positioning**: the TOC is inserted after the last H1 heading, or directly after frontmatter (or at the top) when there is no H1 +- **Auto-update**: optionally refresh an existing TOC automatically as the note changes (debounced, only for notes that already have one) +- **Heading depth control**: exclude H1 headings and cap depth (1–6) +- **Pattern exclusion**: skip headings matching regular expressions (validated in settings) +- **Link options**: clickable wikilink entries or plain text +- **Custom title**: personalize the TOC heading +- **Removal command**: cleanly delete the TOC section and its frontmatter key ## Installation ### From Obsidian Community Plugins 1. Open Obsidian Settings → Community Plugins -2. Disable Safe Mode if needed -3. Search for "Table of Contents Generator" -4. Install and enable the plugin +2. Search for "Table of Contents Generator" +3. Install and enable the plugin ### Manual Installation 1. Download the latest release from GitHub @@ -50,68 +35,67 @@ This plugin differs from other TOC solutions in several key ways: ## Usage -### Basic Usage 1. Open any note with headings -2. Run command `Generate table of contents` or click the TOC ribbon icon -3. The TOC will be intelligently positioned at document start or after the last H1 heading +2. Run the command `Generate table of contents` or click the ribbon icon +3. Run it again at any time to refresh, or enable auto-update in settings ### Generated TOC Example ```markdown --- toc: generated: true - lastUpdate: "2025-01-15T10:30:00Z" --- +# My Note ## Table of Contents + - [[#Introduction|Introduction]] - [[#Getting Started|Getting Started]] - [[#Advanced Features|Advanced Features]] - - [[#Configuration Options|Configuration Options]] + +## Introduction +... ``` -### Configuration Options +Duplicate heading names are listed, but only the first occurrence is linked — Obsidian wikilinks cannot address later occurrences of the same heading text. -Access settings via Settings → Community Plugins → Table of Contents Generator +## Settings -#### Content Settings -- **TOC Title**: Customize the heading text (default: "Table of Contents") -- **Include Links**: Toggle clickable navigation links to headings -- **Exclude H1**: Skip document title headings from TOC -- **Maximum Depth**: Limit heading levels (1-6, default: 4) - -#### Positioning -- **Smart Positioning**: Automatically places TOC at document start or after the last H1 heading - -#### Filtering & Updates -- **Exclude Patterns**: Regex patterns to skip specific headings -- **Auto-Update**: Automatically refresh TOC when document changes -- **ReDoS Protection**: Safe regex validation prevents performance issues +- **Table of contents title** (default: "Table of Contents") +- **Exclude level 1 headings** (default: on) +- **Maximum heading depth** (1–6, default: 4) +- **Include links** (default: on) +- **Exclude patterns**: one regex per line; invalid patterns are flagged and not saved +- **Auto-update table of contents**: refresh an existing TOC whenever the note changes on disk (default: off) ## Commands -- **Generate table of contents**: Insert or refresh the TOC for the active note -- **Debug TOC metadata**: Diagnostic tool to inspect TOC state and troubleshoot issues +- **Generate table of contents**: insert or refresh the TOC in the active note +- **Remove table of contents**: delete the TOC section and its `toc` frontmatter key ## Technical Details -### Frontmatter Metadata -The plugin tracks TOC state using minimal YAML frontmatter: +The plugin marks TOC-managed notes with a minimal frontmatter key, written via Obsidian's `processFrontMatter` API (your other frontmatter is never rewritten by hand): + ```yaml --- toc: - generated: true # TOC exists in document - lastUpdate: "2025-01-15T10:30:00Z" # ISO timestamp of last update + generated: true --- ``` -### Architecture -- **Performance Optimized**: 75% reduction in regex operations with pre-compiled patterns -- **Security Hardened**: Comprehensive ReDoS protection against 10+ dangerous patterns -- **Service-Oriented Design**: Modular components with centralized TOC detection logic -- **TypeScript**: Full type safety with strict compliance and modern ES2020 features -- **Memory Efficient**: Proper cleanup, surgical updates, and optimized string operations -- **Modern Build System**: esbuild with security-focused dependencies and zero runtime deps +The TOC section itself is located by matching an H2 against your configured title or the common aliases "Table of Contents", "TOC", "Contents", "Index", and "Outline" — headings inside code fences are ignored. Requires Obsidian 1.7.2+. + +### Development + +```bash +npm install +npm run dev # watch build +npm test # vitest unit tests +npm run build # typecheck + production build +``` + +Core logic lives in `src/` as pure, unit-tested functions (`toc-section.ts`, `toc-generator.ts`, `heading-filter.ts`); `main.ts` contains only Obsidian wiring. ## Feedback diff --git a/manifest.json b/manifest.json index 64d973a..2101a47 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,8 @@ { "id": "table-of-contents-generator", "name": "Table of Contents Generator", - "version": "1.0.0", - "minAppVersion": "0.15.0", + "version": "1.1.0", + "minAppVersion": "1.7.2", "description": "Generate a table of contents for your notes", "author": "Matt Kaili", "authorUrl": "https://github.com/m-kk", diff --git a/versions.json b/versions.json index 26382a1..eab5ec9 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,4 @@ { - "1.0.0": "0.15.0" + "1.0.0": "0.15.0", + "1.1.0": "1.7.2" }