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

@type-editor/changeset

v0.0.3

Published

This is a refactored version of the ProseMirror's 'changeset' module. Original: https://github.com/ProseMirror/prosemirror-changeset

Downloads

20

Readme

@type-editor/changeset

A refactored version of ProseMirror's prosemirror-changeset module, providing tools for tracking and comparing document changes over time.

Installation

npm install @type-editor/changeset

Overview

This module provides utilities for tracking changes to a document from a given point in the past. It condenses step maps down to a flat sequence of replacements and simplifies replacements that partially undo themselves by comparing their content.

The ChangeSet maintains two coordinate systems:

  • A coordinates: Positions in the original (starting) document
  • B coordinates: Positions in the current (modified) document

Use Cases

  • Track Changes: Visualize insertions and deletions in collaborative editing
  • Change History: Build "diff view" features showing document modifications
  • Attribution: Track which users made which changes when combined with metadata

Core Classes

ChangeSet

The main class for tracking document changes. A ChangeSet collects and simplifies a sequence of document modifications, making it easy to visualize what changed between two document states.

import { ChangeSet } from '@type-editor/changeset';

// Create a changeset from a starting document
const changeSet = ChangeSet.create(startDoc);

// Add steps as document changes occur
const updated = changeSet.addSteps(newDoc, stepMaps, metadata);

// Access the tracked changes
for (const change of updated.changes) {
  console.log(`Replaced ${change.fromA}-${change.toA} with content at ${change.fromB}-${change.toB}`);
}

Methods

| Method | Description | |----------------------------------------|---------------------------------------------------------------------| | create(doc, combine?, tokenEncoder?) | Creates a new changeset tracking from the given document. | | addSteps(doc, stepMaps, data?) | Computes a new changeset by adding step maps and optional metadata. | | changes | The array of changes tracked from the starting document. | | startDoc | The starting document that changes are tracked relative to. |

Change

Represents a change between two document versions. A Change tracks a replaced range in the document, including both what was deleted from the old version and what was inserted in the new version.

interface Change<Data> {
  fromA: number;   // Start position in old document
  toA: number;     // End position in old document
  fromB: number;   // Start position in new document
  toB: number;     // End position in new document
  deleted: ReadonlyArray<Span<Data>>;   // Metadata spans for deleted content
  inserted: ReadonlyArray<Span<Data>>; // Metadata spans for inserted content
}

Methods

| Method | Description | |-------------------------|-----------------------------------------------------------------------------| | fromJSON(json) | Static method that deserializes a Change from its JSON representation. | | toJSON() | Serializes this Change to a JSON-compatible representation. | | slice(startA, endA, startB, endB) | Creates a sub-change by slicing ranges from both coordinate systems. |

Serialization Example

import { Change } from '@type-editor/changeset';

// Serialize a change to JSON
const json = change.toJSON();

// Deserialize a change from JSON
const restored = Change.fromJSON(json);

Span

Stores metadata for a part of a change. A Span represents a contiguous range in a document with associated metadata.

import { Span } from '@type-editor/changeset';

const span = new Span(10, { author: 'user1' });
console.log(span.length); // 10
console.log(span.data);   // { author: 'user1' }

Utility Functions

computeDiff

Computes the difference between two document fragments using Myers' diff algorithm.

import { computeDiff } from '@type-editor/changeset';

const changes = computeDiff(fragmentA, fragmentB, range);

simplifyChanges

Simplifies a set of changes for presentation by expanding insertions and deletions to word boundaries.

import { simplifyChanges } from '@type-editor/changeset';

const simplified = simplifyChanges(changes, document);

Token Encoder

A TokenEncoder can be provided when creating a ChangeSet to influence how the diffing algorithm compares document content. The default encoder compares nodes by name and text by character, ignoring marks and attributes.

import type { TokenEncoder } from '@type-editor/changeset';

const customEncoder: TokenEncoder<string> = {
  encodeCharacter: (char, marks) => String.fromCharCode(char),
  encodeNodeStart: (node) => node.type.name,
  encodeNodeEnd: (node) => `/${node.type.name}`,
  compareTokens: (a, b) => a === b
};

const changeSet = ChangeSet.create(doc, combine, customEncoder);

TokenEncoder Interface

| Method | Description | |--------------------------------|-----------------------------------------------------| | encodeCharacter(char, marks) | Encode a character with its applied marks. | | encodeNodeStart(node) | Encode the start of a node or the entire leaf node. | | encodeNodeEnd(node) | Encode the end token for a node. | | compareTokens(a, b) | Compare two encoded tokens for equality. |

License

MIT