> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/ueberdosis/tiptap/llms.txt
> Use this file to discover all available pages before exploring further.

# Editor

> The Editor class is the heart of Tiptap. Learn how to create, configure, and control your editor instance.

The `Editor` class is the core of Tiptap. It manages the editor state, handles transactions, and provides methods to interact with your content.

## Creating an Editor

The simplest way to create an editor is to instantiate the `Editor` class:

```typescript theme={null}
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'

const editor = new Editor({
  element: document.querySelector('.editor'),
  extensions: [
    StarterKit,
  ],
  content: '<p>Hello World!</p>',
})
```

## Editor Options

The `Editor` constructor accepts a configuration object with the following options:

<ParamField path="element" type="HTMLElement | null">
  The DOM element where the editor should be mounted. Can be `null` if you want to mount it later.
</ParamField>

<ParamField path="content" type="string | JSONContent">
  The initial content of the editor. Can be HTML string or JSON.

  ```typescript theme={null}
  // HTML content
  content: '<p>Hello World!</p>'

  // JSON content
  content: {
    type: 'doc',
    content: [
      {
        type: 'paragraph',
        content: [{ type: 'text', text: 'Hello World!' }]
      }
    ]
  }
  ```
</ParamField>

<ParamField path="extensions" type="Extension[]" default="[]">
  An array of extensions to use in the editor. Extensions add functionality like nodes, marks, and commands.
</ParamField>

<ParamField path="editable" type="boolean" default="true">
  Whether the editor is editable.
</ParamField>

<ParamField path="autofocus" type="boolean | 'start' | 'end' | number" default="false">
  Whether the editor should be focused on initialization.

  * `true` or `'start'`: Focus at the start
  * `'end'`: Focus at the end
  * `number`: Focus at a specific position
</ParamField>

<ParamField path="injectCSS" type="boolean" default="true">
  Whether to inject the default Tiptap CSS styles.
</ParamField>

<ParamField path="enableInputRules" type="boolean" default="true">
  Whether to enable input rules (e.g., markdown shortcuts).
</ParamField>

<ParamField path="enablePasteRules" type="boolean" default="true">
  Whether to enable paste rules.
</ParamField>

<ParamField path="enableCoreExtensions" type="boolean" default="true">
  Whether to enable core extensions (required for basic functionality).
</ParamField>

## Event Handlers

The editor emits events at different stages of its lifecycle:

<ParamField path="onCreate" type="({ editor }) => void">
  Called when the editor is created and ready.

  ```typescript theme={null}
  onCreate: ({ editor }) => {
    console.log('Editor is ready!', editor.getHTML())
  }
  ```
</ParamField>

<ParamField path="onUpdate" type="({ editor, transaction }) => void">
  Called whenever the document changes.

  ```typescript theme={null}
  onUpdate: ({ editor }) => {
    const html = editor.getHTML()
    console.log('Content updated:', html)
  }
  ```
</ParamField>

<ParamField path="onSelectionUpdate" type="({ editor }) => void">
  Called when the selection changes.
</ParamField>

<ParamField path="onTransaction" type="({ editor, transaction }) => void">
  Called for every transaction (even if the document didn't change).
</ParamField>

<ParamField path="onFocus" type="({ editor, event }) => void">
  Called when the editor receives focus.
</ParamField>

<ParamField path="onBlur" type="({ editor, event }) => void">
  Called when the editor loses focus.
</ParamField>

<ParamField path="onDestroy" type="() => void">
  Called when the editor is destroyed.
</ParamField>

## Core Methods

### Content Methods

<ResponseField name="setContent" type="(content: string | JSONContent, options?: SetContentOptions) => Editor">
  Replace the entire document with new content.

  ```typescript theme={null}
  // Set HTML content
  editor.commands.setContent('<p>New content</p>')

  // Set JSON content
  editor.commands.setContent({
    type: 'doc',
    content: [
      { type: 'paragraph', content: [{ type: 'text', text: 'New content' }] }
    ]
  })

  // Don't emit update event
  editor.commands.setContent('<p>New content</p>', { emitUpdate: false })
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/commands/setContent.ts:35`
</ResponseField>

<ResponseField name="getHTML" type="() => string">
  Get the current document as HTML.

  ```typescript theme={null}
  const html = editor.getHTML()
  // Returns: '<p>Hello World!</p>'
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:737`
</ResponseField>

<ResponseField name="getJSON" type="() => JSONContent">
  Get the current document as JSON.

  ```typescript theme={null}
  const json = editor.getJSON()
  // Returns: { type: 'doc', content: [...] }
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:727`
</ResponseField>

<ResponseField name="getText" type="(options?: { blockSeparator?: string }) => string">
  Get the current document as plain text.

  ```typescript theme={null}
  const text = editor.getText()
  // Returns: 'Hello World!'

  // Custom separator between blocks
  const text = editor.getText({ blockSeparator: ' ' })
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:744`
</ResponseField>

### Focus Methods

<ResponseField name="focus" type="(position?: 'start' | 'end' | number | boolean) => Editor">
  Focus the editor at a specific position.

  ```typescript theme={null}
  // Focus at current position
  editor.commands.focus()

  // Focus at start
  editor.commands.focus('start')

  // Focus at end
  editor.commands.focus('end')

  // Focus at specific position
  editor.commands.focus(10)
  ```
</ResponseField>

<ResponseField name="blur" type="() => Editor">
  Remove focus from the editor.

  ```typescript theme={null}
  editor.commands.blur()
  ```
</ResponseField>

### Lifecycle Methods

<ResponseField name="mount" type="(element: HTMLElement) => void">
  Mount the editor to a DOM element.

  ```typescript theme={null}
  const editor = new Editor({
    extensions: [StarterKit],
  })

  // Mount later
  const element = document.querySelector('.editor')
  editor.mount(element)
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:161`
</ResponseField>

<ResponseField name="unmount" type="() => void">
  Unmount the editor from the DOM (but keep it in memory for later remounting).

  ```typescript theme={null}
  editor.unmount()
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:190`
</ResponseField>

<ResponseField name="destroy" type="() => void">
  Destroy the editor and clean up all resources.

  ```typescript theme={null}
  editor.destroy()
  ```

  <Warning>
    After calling `destroy()`, the editor instance cannot be reused. Create a new editor if needed.
  </Warning>

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:766`
</ResponseField>

## Properties

<ResponseField name="commands" type="SingleCommands">
  Access to all registered commands.

  ```typescript theme={null}
  editor.commands.setContent('<p>Hello</p>')
  editor.commands.toggleBold()
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:232`
</ResponseField>

<ResponseField name="schema" type="Schema">
  The ProseMirror schema generated from your extensions.

  ```typescript theme={null}
  console.log(editor.schema)
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:65`
</ResponseField>

<ResponseField name="view" type="EditorView">
  The ProseMirror editor view.

  ```typescript theme={null}
  console.log(editor.view)
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:305`
</ResponseField>

<ResponseField name="state" type="EditorState">
  The current ProseMirror editor state.

  ```typescript theme={null}
  console.log(editor.state.selection)
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:353`
</ResponseField>

<ResponseField name="isFocused" type="boolean">
  Whether the editor currently has focus.

  ```typescript theme={null}
  if (editor.isFocused) {
    console.log('Editor is focused')
  }
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:69`
</ResponseField>

<ResponseField name="isEditable" type="boolean">
  Whether the editor is editable.

  ```typescript theme={null}
  if (editor.isEditable) {
    console.log('Editor is editable')
  }
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:295`
</ResponseField>

<ResponseField name="isEmpty" type="boolean">
  Whether the editor content is empty.

  ```typescript theme={null}
  if (editor.isEmpty) {
    console.log('Editor is empty')
  }
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:759`
</ResponseField>

<ResponseField name="isDestroyed" type="boolean">
  Whether the editor has been destroyed.

  ```typescript theme={null}
  if (editor.isDestroyed) {
    console.log('Editor is destroyed')
  }
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:777`
</ResponseField>

<ResponseField name="storage" type="Storage">
  Access to extension storage.

  ```typescript theme={null}
  // Access storage from a specific extension
  const count = editor.storage.characterCount.characters()
  ```

  Source: `/home/daytona/workspace/source/packages/core/src/Editor.ts:225`
</ResponseField>

## Advanced Usage

### Making the Editor Read-only

```typescript theme={null}
// Set editable state
editor.setEditable(false)

// Check if editable
if (editor.isEditable) {
  console.log('Editor is editable')
}
```

### Checking Active State

```typescript theme={null}
// Check if bold is active
if (editor.isActive('bold')) {
  console.log('Bold is active')
}

// Check if heading level 1 is active
if (editor.isActive('heading', { level: 1 })) {
  console.log('H1 is active')
}

// Check if link with specific href is active
if (editor.isActive('link', { href: 'https://example.com' })) {
  console.log('Link is active')
}
```

### Getting Attributes

```typescript theme={null}
// Get attributes of current node/mark
const attrs = editor.getAttributes('link')
console.log(attrs.href)

// Get heading level
const headingAttrs = editor.getAttributes('heading')
console.log(headingAttrs.level) // 1, 2, 3, etc.
```

### Working with Selection

```typescript theme={null}
// Get current selection
const { from, to } = editor.state.selection

// Get selected text
const selectedText = editor.state.doc.textBetween(from, to)

// Check if selection is empty
const isEmpty = editor.state.selection.empty
```

## TypeScript Types

```typescript theme={null}
import type { Editor, EditorOptions, EditorEvents } from '@tiptap/core'

// Editor options type
const options: Partial<EditorOptions> = {
  content: '<p>Hello</p>',
  editable: true,
}

// Event handler types
type OnUpdate = EditorEvents['update']
// { editor: Editor, transaction: Transaction, appendedTransactions: Transaction[] }

type OnCreate = EditorEvents['create']
// { editor: Editor }
```

## Best Practices

<Card title="Clean Up Resources" icon="broom">
  Always call `editor.destroy()` when you're done with an editor instance to prevent memory leaks.

  ```typescript theme={null}
  useEffect(() => {
    const editor = new Editor({ /* ... */ })
    
    return () => {
      editor.destroy()
    }
  }, [])
  ```
</Card>

<Card title="Batch Updates" icon="layer-group">
  Use command chains to batch multiple updates into a single transaction.

  ```typescript theme={null}
  // Bad: Multiple transactions
  editor.commands.setBold()
  editor.commands.setItalic()

  // Good: Single transaction
  editor.chain().setBold().setItalic().run()
  ```
</Card>

<Card title="Check Before Acting" icon="clipboard-check">
  Use `editor.can()` to check if a command can be executed before running it.

  ```typescript theme={null}
  if (editor.can().toggleBold()) {
    editor.commands.toggleBold()
  }
  ```
</Card>

## Related

<CardGroup cols={2}>
  <Card title="Commands" icon="terminal" href="/core-concepts/commands">
    Learn about the command system
  </Card>

  <Card title="Extensions" icon="puzzle-piece" href="/core-concepts/extensions">
    Learn about extensions
  </Card>

  <Card title="Schema" icon="diagram-project" href="/core-concepts/schema">
    Learn about the ProseMirror schema
  </Card>

  <Card title="Nodes & Marks" icon="cube" href="/core-concepts/nodes-and-marks">
    Learn about content structure
  </Card>
</CardGroup>
