npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tiptap-track-changes

v0.2.1

Published

Open-source track changes (suggesting mode) extension for Tiptap

Readme

tiptap-track-changes

npm version license

Open-source track changes / suggesting mode extension for Tiptap. Adds Google Docs-style change tracking to any Tiptap editor — insertions, deletions, replacements, and format changes are recorded as inline marks that can be individually accepted or rejected.

Live Demo | npm

tiptap-track-changes demo showing multi-author suggesting mode with review sidebar

Install

npm install tiptap-track-changes
yarn add tiptap-track-changes
pnpm add tiptap-track-changes

Peer dependencies: @tiptap/core and @tiptap/pm (v2+). You probably already have these if you're using Tiptap.

Features

  • Three editor modes: edit (direct changes), suggest (tracked proposals), view (read-only)
  • Inline change tracking: Insertions, deletions, replacements, and format changes (bold, italic, etc.)
  • Per-change accept/reject: Accept or reject individual changes, or batch accept/reject all
  • Multi-author support: Each author gets a name, ID, and color — changes are attributed and color-coded
  • Node-level tracking: Paragraph splits (Enter key), block boundary deletions (Backspace/Delete across paragraphs), and block type changes (paragraph to heading)
  • Undo/redo integration: Tracked changes work correctly with Tiptap's built-in history extension
  • Complex script support: Tested with RTL (Arabic, Hebrew), Khmer, Thai, CJK, Devanagari, and other complex scripts
  • 200+ tests: Comprehensive test suite covering edge cases, multi-author scenarios, and complex scripts

Quick Start

import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import History from '@tiptap/extension-history'
import { TrackChangesExtension } from 'tiptap-track-changes'

const editor = new Editor({
  element: document.querySelector('#editor'),
  extensions: [
    Document,
    Paragraph,
    Text,
    History,
    TrackChangesExtension.configure({
      author: {
        id: 'user-1',
        name: 'Alice',
        color: '#2d5fce',
      },
      mode: 'suggest', // start in suggesting mode
      onStatusChange: (changeId, status) => {
        console.log(`Change ${changeId} was ${status}`)
      },
    }),
  ],
  content: '<p>Hello world</p>',
})

Any edits made while in suggest mode are tracked as proposed changes with inline visual markers.

Commands

// Switch modes
editor.commands.setSuggestMode()
editor.commands.setEditMode()
editor.commands.setViewMode()
editor.commands.setTrackChangesMode('suggest') // programmatic

// Change author (e.g., when switching users)
editor.commands.setTrackChangesAuthor({
  id: 'user-2',
  name: 'Bob',
  color: '#c4362c',
})

// Accept/reject individual changes
editor.commands.acceptChange('change-id-here')
editor.commands.rejectChange('change-id-here')

// Accept/reject all pending changes
editor.commands.acceptAll()
editor.commands.rejectAll()

Reading Changes

import {
  getTrackedChanges,
  getGroupedChanges,
  getPendingChangeCount,
  getBaseText,
  getResultText,
} from 'tiptap-track-changes'

// Get all individual tracked change marks
const changes = getTrackedChanges(editor)
// => TrackedChangeInfo[] with changeId, type, authorId, from, to, text, etc.

// Get changes grouped by changeId (insertion + deletion = replacement)
const groups = getGroupedChanges(editor)
// => Map<string, TrackedChangeInfo[]>

// Count pending changes
const count = getPendingChangeCount(editor) // => number

// Get document text with all changes rejected (original) or accepted (result)
const original = getBaseText(editor)
const result = getResultText(editor)

Types

interface ChangeAuthor {
  id: string
  name: string
  color: string
}

type TrackChangesMode = 'edit' | 'suggest' | 'view'

interface TrackChangesOptions {
  author: ChangeAuthor
  mode?: TrackChangesMode
  onStatusChange?: (changeId: string, status: 'accepted' | 'rejected') => void
}

interface TrackedChangeInfo {
  changeId: string
  type: 'insertion' | 'deletion' | 'formatChange' | 'nodeChange'
  authorId: string
  authorName: string
  authorColor: string
  timestamp: string
  from: number
  to: number
  text: string
  formatAdded?: string
  formatRemoved?: string
}

How It Works

In suggest mode, the extension intercepts text input, deletions, Enter key, and format toggles. Instead of modifying the document directly, it wraps changes in inline marks:

  • Insertions: Text is inserted and wrapped in an insertion mark (rendered as <ins>)
  • Deletions: Text is kept in the document but wrapped in a deletion mark (rendered as <del> with CSS to hide it visually)
  • Replacements: A deletion mark on the old text + an insertion mark on the new text, sharing the same changeId
  • Format changes: The format is applied, and a formatChange mark records what was added/removed

When a change is accepted, its marks are removed (insertions become normal text, deletions are removed from the document). When rejected, the opposite happens (insertions are removed, deletions become normal text).

Running the Demo Locally

The demo/ directory contains a full interactive demo with a review sidebar, timeline view, keyboard navigation, and pre-built scenarios.

git clone https://github.com/sungkhum/tiptap-track-changes.git
cd tiptap-track-changes
npm install
cd demo && npm install
cd .. && npm run dev

Or try the hosted demo directly.

Running Tests

npm test          # single run
npm run test:watch # watch mode

Contributing

Contributions are welcome. Please open an issue first to discuss what you'd like to change.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/my-feature)
  3. Run the tests (npm test)
  4. Commit your changes
  5. Open a pull request

License

MIT