or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-tiptap--extension-character-count

Character count extension for Tiptap rich text editor with configurable limits and automatic content trimming

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@tiptap/extension-character-count@3.4.x

To install, run

npx @tessl/cli install tessl/npm-tiptap--extension-character-count@3.4.0

index.mddocs/

Tiptap Character Count Extension

Character count extension for Tiptap rich text editor with configurable limits and automatic content trimming. This extension provides real-time character and word counting functionality with optional character limits, automatic content enforcement, and support for different counting modes.

Package Information

  • Package Name: @tiptap/extension-character-count
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @tiptap/extension-character-count

Core Imports

import { CharacterCount } from "@tiptap/extension-character-count";
import type { CharacterCountOptions } from "@tiptap/extension-character-count";

For default import:

import CharacterCount from "@tiptap/extension-character-count";

For CommonJS:

const { CharacterCount } = require("@tiptap/extension-character-count");

Basic Usage

import { CharacterCount } from "@tiptap/extension-character-count";
import { Editor } from "@tiptap/core";

// Basic usage with default options
const editor = new Editor({
  extensions: [CharacterCount],
  content: "<p>Hello world!</p>",
});

// With character limit
const editor = new Editor({
  extensions: [
    CharacterCount.configure({
      limit: 280,
    })
  ],
  content: "<p>Hello world!</p>",
});

// Access character count
const characterCount = editor.storage.characterCount.characters();
const wordCount = editor.storage.characterCount.words();

console.log(`Characters: ${characterCount}, Words: ${wordCount}`);

Architecture

The extension is built around several key components:

  • Extension Core: Built on Tiptap's Extension framework, integrating with ProseMirror's plugin system
  • Character Counting: Supports both text-based (textSize) and node-based (nodeSize) counting modes
  • Limit Enforcement: Real-time transaction filtering prevents exceeding character limits
  • Content Trimming: Automatic content trimming for pasted content and initialization
  • Storage API: Provides runtime access to character and word counts through editor storage

Capabilities

Character Count Extension

The main extension providing character counting functionality with optional limits and automatic enforcement.

const CharacterCount: Extension<CharacterCountOptions, CharacterCountStorage>;

Configuration Options

Configuration interface for customizing the character count behavior.

interface CharacterCountOptions {
  /**
   * The maximum number of characters that should be allowed. Defaults to null.
   * @default null
   * @example 180
   */
  limit: number | null | undefined;
  
  /**
   * The mode by which the size is calculated. If set to 'textSize', the textContent of the document is used.
   * If set to 'nodeSize', the nodeSize of the document is used.
   * @default 'textSize'
   * @example 'textSize'
   */
  mode: 'textSize' | 'nodeSize';
  
  /**
   * The text counter function to use. Defaults to a simple character count.
   * @default (text) => text.length
   * @example (text) => [...new Intl.Segmenter().segment(text)].length
   */
  textCounter: (text: string) => number;
  
  /**
   * The word counter function to use. Defaults to a simple word count.
   * @default (text) => text.split(' ').filter(word => word !== '').length
   * @example (text) => text.split(/\s+/).filter(word => word !== '').length
   */
  wordCounter: (text: string) => number;
}

Storage Interface

Runtime interface for accessing character and word counts.

interface CharacterCountStorage {
  /**
   * Get the number of characters for the current document.
   * @param options The options for the character count. (optional)
   * @param options.node The node to get the characters from. Defaults to the current document.
   * @param options.mode The mode by which the size is calculated. If set to 'textSize', the textContent of the document is used.
   */
  characters: (options?: { 
    node?: ProseMirrorNode; 
    mode?: 'textSize' | 'nodeSize' 
  }) => number;

  /**
   * Get the number of words for the current document.
   * @param options The options for the character count. (optional)
   * @param options.node The node to get the words from. Defaults to the current document.
   */
  words: (options?: { node?: ProseMirrorNode }) => number;
}

ProseMirror Node Type

Type definition for ProseMirror nodes used in the storage interface.

// Imported from @tiptap/pm/model
import type { Node as ProseMirrorNode } from '@tiptap/pm/model';

Advanced Usage Examples

Custom Character Counting

import { CharacterCount } from "@tiptap/extension-character-count";
import { Editor } from "@tiptap/core";

// Using Unicode-aware character counting
const editor = new Editor({
  extensions: [
    CharacterCount.configure({
      limit: 280,
      textCounter: (text) => {
        // Count grapheme clusters instead of code units
        return [...new Intl.Segmenter().segment(text)].length;
      },
    })
  ],
});

Custom Word Counting

import { CharacterCount } from "@tiptap/extension-character-count";
import { Editor } from "@tiptap/core";

// Using custom word counting logic
const editor = new Editor({
  extensions: [
    CharacterCount.configure({
      wordCounter: (text) => {
        // Split on any whitespace and filter empty strings
        return text.split(/\s+/).filter(word => word !== '').length;
      },
    })
  ],
});

Node Size Mode

import { CharacterCount } from "@tiptap/extension-character-count";
import { Editor } from "@tiptap/core";

// Use nodeSize instead of textContent for counting
const editor = new Editor({
  extensions: [
    CharacterCount.configure({
      mode: 'nodeSize',
      limit: 1000,
    })
  ],
});

Runtime Character Count Access

import { CharacterCount } from "@tiptap/extension-character-count";
import { Editor } from "@tiptap/core";

const editor = new Editor({
  extensions: [CharacterCount],
});

// Get counts for current document
const chars = editor.storage.characterCount.characters();
const words = editor.storage.characterCount.words();

// Get counts for specific node with custom mode
const nodeChars = editor.storage.characterCount.characters({
  node: someSpecificNode,
  mode: 'nodeSize'
});

// Get word count for specific node
const nodeWords = editor.storage.characterCount.words({
  node: someSpecificNode
});

Limit Enforcement Behavior

The extension automatically enforces character limits through ProseMirror's transaction filtering:

  • Normal typing: Prevents typing when at the character limit
  • Pasted content: Automatically trims pasted content to fit within the limit
  • Initial content: Trims initial content that exceeds the limit on editor initialization
  • Complex nodes: Handles cases where trimming within complex nodes (like tables) might still exceed limits
import { CharacterCount } from "@tiptap/extension-character-count";
import { Editor } from "@tiptap/core";

const editor = new Editor({
  extensions: [
    CharacterCount.configure({
      limit: 100, // Strict 100 character limit
    })
  ],
  content: "<p>This content will be automatically trimmed if it exceeds the 100 character limit during initialization</p>",
});

// The editor will automatically prevent further typing at the limit
// and trim any pasted content that would exceed the limit

Error Handling

The extension includes built-in error handling and warnings:

  • Initial content trimming: Console warning when initial content is automatically trimmed
  • Transaction blocking: Silent prevention of transactions that would exceed limits
  • Paste trimming: Automatic handling of oversized pasted content with fallback blocking

No exceptions are thrown during normal operation, making the extension safe to use in production environments.