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-utility

v3.0.1

Published

List of utils functions, helps to build custom extension and help working with tiptap editor

Readme

Tiptap Utility Package

NPM

A collection of utility functions to enhance your workflow with the Tiptap editor.

Installation

npm install tiptap-utility

Utilities

Quick Access

isTextSelected

Checks if text is selected in the Tiptap editor.

Parameters:

  • editor: Tiptap Editor instance.

Returns:

  • boolean: true if text is selected and editor is editable, otherwise false.

Example:

import { isTextSelected } from 'tiptap-utility';

const isSelected = isTextSelected({ editor });
console.log(isSelected ? "Text is selected" : "No text selected");

getWordCount

Counts the number of words in the Tiptap editor content.

Parameters:

  • editor: Tiptap Editor instance.

Returns:

  • number: Total word count.

Example:

import { getWordCount } from 'tiptap-utility';

const wordCount = getWordCount(editor);
console.log(`Word count: ${wordCount}`);

getFocusedNodeContainer

Finds the focused node container in the Tiptap editor DOM based on the specified nodeType.

Parameters:

  • editor: Tiptap Editor instance.
  • nodeType: The target node type to locate.
  • attribute (optional): Attribute used to identify the node. Default is 'data-type'.
  • focusClass (optional): CSS class used to identify focused nodes. Default is 'has-focus'.

Returns:

  • HTMLElement | null: The focused node container or null if not found.

Example:

import { getFocusedNodeContainer } from 'tiptap-utility';

const container = getFocusedNodeContainer(editor, 'paragraph');
if (container) {
  console.log('Focused node container:', container);
} else {
  console.log('No focused container found.');
}

getAllNodesOfType

Retrieves all nodes of a specified type from the Tiptap editor document, including those nested within lists, tables, or other container nodes.

Parameters:

  • editor: Tiptap Editor instance.
  • type: The target node type to locate (e.g., 'heading', 'paragraph').

Returns:

  • Array<{ node: Node, pos: number }>:
    • An array of objects where each object contains:
      • node: The node instance of the specified type.
      • pos: The position of the node in the document.

Example:

import { getAllNodesOfType } from 'tiptap-utility';

const headings = getAllNodesOfType(editor, 'heading');
headings.forEach(({ node, pos }) => {
  console.log('Found heading:', node, 'at position:', pos);
});

getAllNodesByTypeAndAttrs

Finds all nodes of a given type and with specific attributes in the Tiptap editor's document.

Parameters:

  • editor: Tiptap Editor instance.
  • type: A string representing the type of node to search for.
  • attrs: An object containing the attributes to match against the nodes.

Returns:

  • Array<{ node: any; pos: number }>: An array of nodes and their positions that match the given type and attributes.

Example:

import { getAllNodesByTypeAndAttrs } from 'tiptap-utility';

const nodes = getAllNodesByTypeAndAttrs({ editor }, 'image', { src: 'https://example.com/image.jpg' });
console.log(nodes);

getAllMarksByTypeAndAttrs

Finds all marks of a given type and with specific attributes in the Tiptap editor's document.

Parameters:

  • editor: Tiptap Editor instance.
  • markTypeName: A string representing the type of mark to search for (e.g., 'bold', 'italic', 'link').
  • attrs: An object containing the attributes to match against the marks.
  • match (optional): The matching strategy - 'and' (default) requires all attributes to match, 'or' requires at least one attribute to match.

Returns:

  • Array<{ from: number; to: number; attrs: any }>: An array of objects where each object contains:
    • from: The starting position of the marked text.
    • to: The ending position of the marked text.
    • attrs: The attributes of the mark.

Example:

import { getAllMarksByTypeAndAttrs } from 'tiptap-utility';

// Find all bold marks
const boldMarks = getAllMarksByTypeAndAttrs(editor, 'bold', {});
console.log(boldMarks);

// Find all link marks with specific href
const linkMarks = getAllMarksByTypeAndAttrs(editor, 'link', { href: 'https://example.com' });
console.log(linkMarks);

// Find marks where any of the specified attributes match (using 'or' strategy)
const colorMarks = getAllMarksByTypeAndAttrs(editor, 'textStyle', { color: '#ff0000' }, 'or');
console.log(colorMarks);

findParentNodeOfTypeAtPosition

Finds the parent node of a given type at a specific position in the Tiptap editor.

Parameters:

  • editor: Tiptap Editor instance.
  • position: The position in the document where the search for the parent node begins.
  • parentNodeTypeName: The name of the parent node type to search for.

Returns:

  • { node: any; depth: number; start: number; end: number } | null: An object containing the parent node, its depth, and its start and end positions if found, otherwise null.

Example:

import { findParentNodeOfTypeAtPosition } from 'tiptap-utility';

const parentNode = findParentNodeOfTypeAtPosition({ editor }, 10, 'paragraph');
if (parentNode) {
    console.log('Parent node found:', parentNode);
} else {
    console.log('No parent node found at the specified position');
}

getEditorState

Retrieves the current state of the Tiptap editor.

Parameters:

  • editor: Tiptap Editor instance.

Returns:

  • object: The current state of the editor, either from editor.state or editor.view.state.

Example:

import { getEditorState } from 'tiptap-utility';

const editorState = getEditorState({ editor });
console.log(editorState);

getNodesInRange

Extracts all nodes within a specified range in the Tiptap editor document. Optionally, it can filter nodes by specified types.

Parameters

  • editor (required): An instance of the Tiptap Editor.
  • from (required): The starting position of the range (inclusive).
  • to (required): The ending position of the range (exclusive).
  • nodeType (optional): An array of node type names to filter for, or null to include all node types. Defaults to null.

Returns

  • NodeWithPosition[]: An array of objects, where each object contains:
    • node: The ProseMirror Node instance.
    • pos: The starting position of the node within the document.

Example

import { getNodesInRange } from 'tiptap-utility';

const from = 0;
const to = 50;
const nodeTypes = ['paragraph', 'heading'];

const nodes = getNodesInRange(editor, from, to, nodeTypes);

nodes.forEach(({ node, pos }) => {
  console.log(`Node of type ${node.type.name} found at position ${pos}`);
});

getLastChildNode

Retrieves the last child node of a given node along with its starting position.

Parameters

  • node (required): A ProseMirror Node from which to find the last child.

Returns

  • { node: Node, pos: number } | null:
    • If the node has child nodes, returns an object containing:
      • node: The last child Node.
      • pos: The starting position of the last child node.
    • Returns null if the node has no children.

Example

import { getLastChildNode } from 'tiptap-utility';

const parentNode = editor.state.doc.nodeAt(0); // Example parent node

if (parentNode) {
  const lastChild = getLastChildNode(parentNode);
  if (lastChild) {
    console.log(`Last child node type: ${lastChild.node.type.name}`);
    console.log(`Position: ${lastChild.pos}`);
  } else {
    console.log('No child nodes found.');
  }
}

getNextSiblingNode

Finds the next sibling node of a given node within its parent.

Parameters

  • parent (required): A ProseMirror Node representing the parent container.
  • currentNode (required): The child node whose next sibling needs to be found.

Returns

  • { node: Node } | null:
    • If a next sibling exists, returns an object containing:
      • node: The next sibling Node.
    • Returns null if there is no next sibling.

Example

import { getNextSiblingNode } from 'tiptap-utility';

const parentNode = editor.state.doc.nodeAt(0); // Example parent node
const currentNode = parentNode?.firstChild; // Example current node

if (parentNode && currentNode) {
  const nextSibling = getNextSiblingNode(parentNode, currentNode);
  if (nextSibling) {
    console.log(`Next sibling node type: ${nextSibling.node.type.name}`);
  } else {
    console.log('No next sibling found.');
  }
}

mapEachNode

Recursively traverses a Tiptap JSONContent node tree and applies a callback to each node. Useful for transforming or inspecting every node in a document (e.g. changing node types, stripping marks, or collecting stats). The tree is traversed in place; the callback can return a modified or replaced node.

Parameters

  • node (required): A Tiptap JSONContent object (e.g. from editor.getJSON() or a single node).
  • callback (required): A function (node: JSONContent) => JSONContent called for each node that has a type property. Return the same or a modified node; that value is used for that node in the tree.

Returns

  • JSONContent: The root node after applying the callback to it and recursively to all descendants. The original structure is mutated.

Example

import { mapEachNode } from 'tiptap-utility';

const json = editor.getJSON();

// Example: ensure every paragraph has an empty attrs object
const normalized = mapEachNode(json, (node) => {
  if (node.type === 'paragraph' && !node.attrs) {
    return { ...node, attrs: {} };
  }
  return node;
});

// Example: collect all node types (inspect only)
const types: string[] = [];
mapEachNode(json, (node) => {
  if (node.type) types.push(node.type);
  return node;
});
console.log('Node types in document:', types);

filterEachNode

Recursively traverses a Tiptap JSONContent node tree and returns a new tree containing only nodes that pass a predicate. Does not mutate the input. Useful for stripping certain node types (e.g. images, embeds) or building a reduced copy of the document.

Parameters

  • node (required): A Tiptap JSONContent object (e.g. from editor.getJSON() or a single node).
  • predicate (required): A function (node: JSONContent) => boolean called for each node that has a type property. Return true to keep the node (and its filtered subtree), false to remove it.

Returns

  • JSONContent | null: A new tree with only nodes for which the predicate returned true. Returns null if the root node is filtered out. The original structure is not mutated.

Example

import { filterEachNode } from 'tiptap-utility';

const json = editor.getJSON();

// Remove all image nodes from the document
const withoutImages = filterEachNode(json, (node) => node.type !== 'image');

// Keep only block-level nodes (e.g. for a plain-text outline)
const blocksOnly = filterEachNode(json, (node) =>
  ['paragraph', 'heading', 'blockquote', 'listItem'].includes(node.type ?? '')
);

License

This package is open-source and available under the MIT License.