or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

command-system.mddocument-helpers.mdeditor-core.mdextension-system.mdindex.mdrule-systems.mdutilities.md
tile.json

tessl/npm-tiptap--core

Headless rich text editor built on ProseMirror with extensible architecture for building custom editors

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@tiptap/core@3.4.x

To install, run

npx @tessl/cli install tessl/npm-tiptap--core@3.4.0

index.mddocs/

@tiptap/core

@tiptap/core is a headless rich text editor built on top of ProseMirror. It provides a flexible, extensible architecture for building custom rich text editors with nodes, marks, extensions, and commands. The library is framework-agnostic and can be integrated with React, Vue, Svelte, or used in vanilla JavaScript/TypeScript applications.

Package Information

  • Package Name: @tiptap/core
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @tiptap/core @tiptap/pm
  • Peer Dependencies: @tiptap/pm (ProseMirror packages wrapper)

Core Imports

import { Editor, Extension, Node, Mark } from '@tiptap/core';

For CommonJS:

const { Editor, Extension, Node, Mark } = require('@tiptap/core');

JSX Runtime (optional):

import { createElement, Fragment, h } from '@tiptap/core';

Basic Usage

import { Editor, Extension } from '@tiptap/core';

// Create a basic extension
const BasicExtension = Extension.create({
  name: 'basicExtension',
  
  addCommands() {
    return {
      insertText: (text: string) => ({ commands }) => {
        return commands.insertContent(text);
      }
    };
  }
});

// Create and mount editor
const editor = new Editor({
  element: document.querySelector('#editor'),
  content: '<p>Hello World!</p>',
  extensions: [BasicExtension],
  onUpdate: ({ editor }) => {
    console.log('Content updated:', editor.getHTML());
  }
});

// Use commands
editor.commands.insertText('Hello Tiptap!');

// Chain commands
editor
  .chain()
  .focus()
  .insertContent('More content')
  .run();

// Check if commands can be executed
if (editor.can().insertContent('test')) {
  editor.commands.insertContent('test');
}

Architecture

@tiptap/core is built around several key components:

  • Editor: The central editor instance that manages state, view, extensions, and commands
  • Extensions: Modular functionality that can be added to the editor (non-content features)
  • Nodes: Document content structures (paragraphs, headings, lists, etc.)
  • Marks: Text formatting (bold, italic, links, etc.)
  • Commands: Actions that can be performed on the editor
  • Rules: Input and paste transformation rules for shortcuts and content processing
  • Views: Custom DOM representations for nodes and marks
  • Helpers: Utility functions for document manipulation and querying

Capabilities

Editor Core

Central editor class that manages the editor state, extensions, and provides the main API interface.

class Editor {
  constructor(options: Partial<EditorOptions>);
  
  // Core properties
  view: EditorView;
  state: EditorState;
  schema: Schema;
  storage: Storage;
  isEditable: boolean;
  isFocused: boolean;
  isEmpty: boolean;
  isDestroyed: boolean;
  isInitialized: boolean;
  
  // Lifecycle methods
  mount(element?: Element): Editor;
  unmount(): Editor;
  destroy(): void;
  
  // Command execution
  commands: SingleCommands;
  chain(): ChainedCommands;
  can(): CanCommands;
  
  // Content methods
  getHTML(): string;
  getJSON(): JSONContent;
  getText(options?: GetTextOptions): string;
  setOptions(options: Partial<EditorOptions>): void;
  setEditable(editable: boolean): void;
  
  // State inspection
  getAttributes(nameOrType: string | NodeType | MarkType): Record<string, any>;
  isActive(name: string, attributes?: Record<string, any>): boolean;
  
  // Content querying
  $pos(pos: number): NodePos;
  $node(selector: string, attributes?: Record<string, any>): NodePos | null;
  $nodes(selector: string, attributes?: Record<string, any>): NodePos[];
  
  // Plugin management
  registerPlugin(plugin: Plugin, handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[]): EditorState;
  unregisterPlugin(nameOrPluginKey: string | PluginKey | (string | PluginKey)[]): EditorState | undefined;
}

interface EditorOptions {
  element?: Element;
  content?: Content;
  extensions?: Extensions;
  injectCSS?: boolean;
  injectNonce?: string;
  autofocus?: FocusPosition;
  editable?: boolean;
  editorProps?: EditorProps;
  parseOptions?: ParseOptions;
  enableInputRules?: boolean;
  enablePasteRules?: boolean;
  enableCoreExtensions?: boolean | Record<string, boolean>;
  enableContentCheck?: boolean;
  emitContentError?: boolean;
  coreExtensionOptions?: {
    clipboardTextSerializer?: {
      blockSeparator?: string;
    };
    delete?: {
      asyncDeleteEvents?: boolean;
    };
  };
  onBeforeCreate?(props: EditorEvents['beforeCreate']): void;
  onCreate?(props: EditorEvents['create']): void;
  onMount?(props: EditorEvents['mount']): void;
  onUnmount?(props: EditorEvents['unmount']): void;
  onUpdate?(props: EditorEvents['update']): void;
  onSelectionUpdate?(props: EditorEvents['selectionUpdate']): void;
  onTransaction?(props: EditorEvents['transaction']): void;
  onFocus?(props: EditorEvents['focus']): void;
  onBlur?(props: EditorEvents['blur']): void;
  onContentError?(props: EditorEvents['contentError']): void;
  onDestroy?(): void;
}

Editor Core

Extension System

Flexible extension system for adding functionality to the editor through Extensions, Nodes, and Marks.

class Extension<Options = any, Storage = any> {
  static create<O = any, S = any>(config?: Partial<ExtensionConfig<O, S>>): Extension<O, S>;
  
  configure(options?: Partial<Options>): Extension<Options, Storage>;
  extend<ExtendedOptions = Options, ExtendedStorage = Storage>(
    extendedConfig?: Partial<ExtensionConfig<ExtendedOptions, ExtendedStorage>>
  ): Extension<ExtendedOptions, ExtendedStorage>;
}

class Node<Options = any, Storage = any> {
  static create<O = any, S = any>(config?: Partial<NodeConfig<O, S>>): Node<O, S>;
  
  configure(options?: Partial<Options>): Node<Options, Storage>;
  extend<ExtendedOptions = Options, ExtendedStorage = Storage>(
    extendedConfig?: Partial<NodeConfig<ExtendedOptions, ExtendedStorage>>
  ): Node<ExtendedOptions, ExtendedStorage>;
}

class Mark<Options = any, Storage = any> {
  static create<O = any, S = any>(config?: Partial<MarkConfig<O, S>>): Mark<O, S>;
  
  configure(options?: Partial<Options>): Mark<Options, Storage>;
  extend<ExtendedOptions = Options, ExtendedStorage = Storage>(
    extendedConfig?: Partial<MarkConfig<ExtendedOptions, ExtendedStorage>>
  ): Mark<ExtendedOptions, ExtendedStorage>;
  
  static handleExit(options: { editor: Editor; mark: ProseMirrorMark }): boolean;
}

Extension System

Command System

Powerful command system for executing, chaining, and validating editor actions.

interface SingleCommands {
  [key: string]: (attributes?: Record<string, any>) => boolean;
}

interface ChainedCommands {
  [key: string]: (attributes?: Record<string, any>) => ChainedCommands;
  run(): boolean;
}

interface CanCommands {
  [key: string]: (attributes?: Record<string, any>) => boolean;
}

class CommandManager {
  constructor(props: { editor: Editor; state: EditorState });
  
  readonly commands: SingleCommands;
  chain(): ChainedCommands;
  can(): CanCommands;
  createChain(startTr?: Transaction, shouldDispatch?: boolean): ChainedCommands;
  createCan(startTr?: Transaction): CanCommands;
}

interface CommandProps {
  editor: Editor;
  tr: Transaction;
  commands: SingleCommands;
  can: CanCommands;
  chain: () => ChainedCommands;
  state: EditorState;
  view: EditorView;
  dispatch: ((tr: Transaction) => void) | undefined;
}

Command System

Document Helpers

Comprehensive set of helper functions for document manipulation, content generation, and state inspection.

// Content generation
function generateHTML(doc: JSONContent, extensions: Extensions): string;
function generateJSON(content: string, extensions: Extensions): JSONContent;
function generateText(doc: JSONContent | Node, options?: GenerateTextOptions): string;

// Document creation
function createDocument(
  content: Content,
  schema: Schema,
  parseOptions?: ParseOptions
): ProseMirrorNode;
function createNodeFromContent(
  content: Content,
  schema: Schema,
  options?: CreateNodeFromContentOptions
): ProseMirrorNode | ProseMirrorNode[];

// Content queries
function findChildren(
  node: ProseMirrorNode,
  predicate: (child: ProseMirrorNode) => boolean,
  descend?: boolean
): NodeWithPos[];
function findChildrenInRange(
  node: ProseMirrorNode,
  range: { from: number; to: number },
  predicate: (child: ProseMirrorNode) => boolean,
  descend?: boolean
): NodeWithPos[];

// State inspection
function isActive(
  state: EditorState,
  name?: string | NodeType | MarkType,
  attributes?: Record<string, any>
): boolean;
function getAttributes(
  state: EditorState,
  nameOrType: string | NodeType | MarkType
): Record<string, any>;

Document Helpers

Rule Systems

Input and paste rule systems for creating shortcuts and transforming content on input or paste.

class InputRule {
  constructor(config: {
    find: RegExp | ((value: string) => RegExpMatchArray | null);
    handler: (props: {
      state: EditorState;
      range: { from: number; to: number };
      match: RegExpMatchArray;
      commands: SingleCommands;
      chain: () => ChainedCommands;
      can: () => CanCommands;
    }) => void | null;
  });
}

class PasteRule {
  constructor(config: {
    find: RegExp | ((value: string) => RegExpMatchArray | null);
    handler: (props: {
      state: EditorState;
      range: { from: number; to: number };
      match: RegExpMatchArray;
      commands: SingleCommands;
      chain: () => ChainedCommands;
      can: () => CanCommands;
      pastedText: string;
      dropEvent?: DragEvent;
    }) => void | null;
  });
}

Rule Systems

JSX Runtime Support

Built-in JSX runtime support for creating custom extensions and components using JSX syntax.

/**
 * Create JSX elements for use in extensions
 * @param type - Element type or component
 * @param props - Element properties
 * @param children - Child elements
 * @returns JSX element
 */
function createElement(
  type: string | Component,
  props: Record<string, any> | null,
  ...children: any[]
): JSXElement;

/**
 * JSX Fragment component for wrapping multiple elements
 */
const Fragment: ComponentType;

/**
 * Alias for createElement (h stands for hyperscript)
 */
const h: typeof createElement;

Usage Examples:

import { createElement, Fragment, h } from '@tiptap/core';

// Using createElement directly
const element = createElement('div', { className: 'editor-toolbar' },
  createElement('button', { onClick: () => editor.chain().focus().toggleBold().run() }, 'Bold'),
  createElement('button', { onClick: () => editor.chain().focus().toggleItalic().run() }, 'Italic')
);

// Using JSX syntax (with proper JSX transform)
const toolbar = (
  <div className="editor-toolbar">
    <button onClick={() => editor.chain().focus().toggleBold().run()}>
      Bold
    </button>
    <button onClick={() => editor.chain().focus().toggleItalic().run()}>
      Italic
    </button>
  </div>
);

// Using Fragment
const multipleElements = (
  <Fragment>
    <p>First paragraph</p>
    <p>Second paragraph</p>
  </Fragment>
);

// Using h (hyperscript style)
const hyperscriptElement = h('div', { id: 'editor' },
  h('p', null, 'Content goes here')
);

// In custom extensions
const CustomExtension = Extension.create({
  name: 'customExtension',
  
  addNodeView() {
    return ({ node, getPos, editor }) => {
      const dom = createElement('div', {
        className: 'custom-node',
        'data-type': node.type.name
      }, node.textContent);
      
      return { dom };
    };
  }
});

Utilities

Collection of utility functions for type checking, object manipulation, and platform detection.

// Type guards
function isFunction(value: unknown): value is Function;
function isString(value: unknown): value is string;
function isNumber(value: unknown): value is number;
function isPlainObject(value: unknown): value is Record<string, any>;

// Object utilities
function mergeAttributes(...attributes: Record<string, any>[]): Record<string, any>;
function mergeDeep(target: Record<string, any>, source: Record<string, any>): Record<string, any>;

// Platform detection
function isAndroid(): boolean;
function isiOS(): boolean;
function isMacOS(): boolean;

// DOM utilities
function elementFromString(html: string): Element;
function createStyleTag(css: string, nonce?: string): HTMLStyleElement;

Utilities

Types

// Core types
type Extensions = AnyExtension[];
type AnyExtension = Extension<any, any> | Node<any, any> | Mark<any, any>;

interface JSONContent {
  type?: string;
  attrs?: Record<string, any>;
  content?: JSONContent[];
  marks?: {
    type: string;
    attrs?: Record<string, any>;
  }[];
  text?: string;
}

interface NodeWithPos {
  node: ProseMirrorNode;
  pos: number;
}

// Event types
interface EditorEvents {
  beforeCreate: { editor: Editor };
  create: { editor: Editor };
  mount: { editor: Editor };
  unmount: { editor: Editor };
  update: { editor: Editor; transaction: Transaction; appendedTransactions: Transaction[] };
  selectionUpdate: { editor: Editor; transaction: Transaction };
  transaction: { editor: Editor; transaction: Transaction };
  focus: { editor: Editor; event: FocusEvent; transaction: Transaction };
  blur: { editor: Editor; event: FocusEvent; transaction: Transaction };
  contentError: { 
    editor: Editor; 
    error: Error; 
    disableCollaboration: () => void; 
  };
}

// Configuration types
interface ExtensionConfig<Options = any, Storage = any> {
  name: string;
  defaultOptions?: Options;
  addStorage?(): Storage;
  addCommands?(): Commands;
  addKeymap?(): Record<string, any>;
  addInputRules?(): InputRule[];
  addPasteRules?(): PasteRule[];
  addGlobalAttributes?(): GlobalAttributes[];
  addNodeView?(): NodeViewRenderer;
  onCreate?(this: { options: Options; storage: Storage }): void;
  onUpdate?(this: { options: Options; storage: Storage }): void;
  onDestroy?(this: { options: Options; storage: Storage }): void;
}