Table of Contents Extension for TipTap v2
A TipTap extension that automatically generates and manages a table of contents from document headings.
Note: This extension is fully compatible with the official TipTap Table of Contents extension. For more examples and use cases, refer to the official documentation.
Features
- Automatically generates a hierarchical table of contents from document headings
- Supports custom heading types and levels
- Provides scroll position tracking
- Customizable heading ID generation
- Real-time updates as the document changes
- Flexible configuration options for custom implementations
- Support for custom heading types and levels
- Built-in scroll position tracking
- Customizable heading ID generation
Installation
npm i tiptap-extension-table-of-content
Usage
import { TableOfContents } from "tiptap-extension-table-of-content";
const editor = new Editor({
extensions: [
TableOfContents.configure({
anchorTypes: ["heading"],
onUpdate: (items) => {
console.log("Table of contents updated:", items);
},
}),
],
});
Configuration Options
The extension can be configured with the following options:
anchorTypes
The types of nodes to be considered as headings. By default, this is ["heading"]
but can be customized for custom heading extensions.
TableOfContents.configure({
anchorTypes: ["heading", "customAnchorType"],
});
getIndex
Customize how item indexes are calculated. The extension provides two built-in functions:
import {
getLinearIndexes,
getHierarchicalIndexes,
} from "tiptap-extension-table-of-content";
TableOfContents.configure({
getIndex: getLinearIndexes,
});
TableOfContents.configure({
getIndex: getHierarchicalIndexes,
});
TableOfContents.configure({
getIndex: (anchor, previousAnchors, level) => {
return 1;
},
});
getLevel
Customize how heading levels are determined:
TableOfContents.configure({
getLevel: (anchor, previousAnchors) => {
return 1;
},
});
getId
Customize heading ID generation:
TableOfContents.configure({
getId: (content) => {
return slugify(content);
},
});
scrollParent
Specify the scrollable parent element:
TableOfContents.configure({
scrollParent: () => editor.view.dom,
});
onUpdate
Callback function for table of contents updates:
TableOfContents.configure({
onUpdate: (anchors, isCreate) => {
anchors.forEach((anchor) => {
});
},
});
const [anchors, setAnchors] = useState([]);
TableOfContents.configure({
onUpdate: (anchors) => {
setAnchors(anchors);
},
});
const anchors = ref([]);
TableOfContents.configure({
onUpdate: (anchors) => {
anchors.value = anchors;
},
});
Storage
The extension maintains the following storage:
content
: Array of content headings
anchors
: Array of anchor elements
scrollHandler
: Scroll event handler function
scrollPosition
: Current scroll position
Access storage through:
editor.storage.tableOfContents.content;
editor.storage.tableOfContents.anchors;
editor.storage.tableOfContents.scrollHandler;
editor.storage.tableOfContents.scrollPosition;
Anchor Object Structure
Each anchor in the array contains the following properties:
{
dom: HTMLElement;
editor: Editor;
id: string;
isActive: boolean;
isScrolledOver: boolean;
itemIndex: number;
level: number;
node: Node;
originalLevel: number;
pos: number;
textContent: string;
}
Development
Project Structure
src/
├── core/
│ └── TableOfContentsExtension.ts # Main extension implementation
├── utils/
│ └── index.ts # Utility functions
├── types/
│ └── content.ts # Type definitions
├── constants/ # Constants and configuration
└── index.ts # Main entry point
Building
npm run build
Testing
npm test
License
MIT © Manas Gupta
See the LICENSE file for details.