Skip to main content

Overview

The blockquote extension adds support for blockquote nodes, which are used to represent quoted or cited text. Blockquotes can contain one or more block-level nodes.

Installation

npm install @prosekit/extensions

Usage

import { defineBlockquote } from '@prosekit/extensions/blockquote'
import { createEditor } from '@prosekit/core'

const extension = defineBlockquote()
const editor = createEditor({ extension })

API Reference

defineBlockquote()

Defines a blockquote node with commands, keymap, input rules, and node specification. Returns: BlockquoteExtension This extension includes:
  • Node specification
  • Wrapping and unwrapping commands
  • Keyboard shortcuts
  • Input rules for Markdown-style syntax

defineBlockquoteSpec()

Defines only the blockquote node specification. Returns: BlockquoteSpecExtension

defineBlockquoteCommands()

Defines blockquote-related commands. Returns: BlockquoteCommandsExtension

defineBlockquoteKeymap()

Defines keyboard shortcuts for blockquote operations. Returns: PlainExtension

defineBlockquoteInputRule()

Defines input rules for Markdown-style blockquote syntax. Returns: PlainExtension

Node Specification

The blockquote node is defined with the following properties:
  • name: blockquote
  • content: block+ (requires one or more block nodes)
  • group: block
  • defining: true (prevents automatic wrapping)
  • parseDOM: [{ tag: 'blockquote' }]
  • toDOM: Renders as <blockquote> element

Commands

setBlockquote()

Wraps the current selection in a blockquote.
import { useEditor } from '@prosekit/react'

function BlockquoteButton() {
  const editor = useEditor()
  
  return (
    <button onClick={() => editor.commands.setBlockquote()}>
      Quote
    </button>
  )
}
Command signature:
setBlockquote: []

insertBlockquote()

Inserts a new empty blockquote node.
editor.commands.insertBlockquote()
Command signature:
insertBlockquote: []

toggleBlockquote()

Toggles blockquote wrapping for the current selection. If the selection is already in a blockquote, it unwraps it; otherwise, it wraps the selection.
editor.commands.toggleBlockquote()
Command signature:
toggleBlockquote: []

Keyboard Shortcuts

ShortcutAction
Mod-BToggle blockquote
BackspaceUnwrap blockquote when at start of first child block
Note: Mod is Cmd on macOS and Ctrl on Windows/Linux.

Input Rules

The extension supports Markdown-style blockquote syntax:
> + space → Blockquote
Type > followed by a space at the start of a line to wrap it in a blockquote.

Examples

Basic Setup

import { createEditor } from '@prosekit/core'
import { union } from '@prosekit/core'
import { defineDoc } from '@prosekit/extensions/doc'
import { defineParagraph } from '@prosekit/extensions/paragraph'
import { defineBlockquote } from '@prosekit/extensions/blockquote'
import { defineText } from '@prosekit/extensions/text'

const extension = union([
  defineDoc(),
  defineParagraph(),
  defineBlockquote(),
  defineText(),
])

const editor = createEditor({ extension })

Toggle Button

import { useEditor } from '@prosekit/react'
import { Button } from './ui/button'

function BlockquoteToggle() {
  const editor = useEditor()
  
  const isActive = editor.nodes.blockquote.isActive()
  
  return (
    <Button
      onClick={() => editor.commands.toggleBlockquote()}
      data-active={isActive}
      aria-label="Toggle blockquote"
    >
      <QuoteIcon />
    </Button>
  )
}

With Multiple Block Types

import { union } from '@prosekit/core'
import { defineBlockquote } from '@prosekit/extensions/blockquote'
import { defineParagraph } from '@prosekit/extensions/paragraph'
import { defineHeading } from '@prosekit/extensions/heading'

const extension = union([
  defineBlockquote(),
  defineParagraph(),
  defineHeading(),
])

// Now blockquotes can contain paragraphs and headings

Programmatic Control

const editor = useEditor()

// Check if selection is in a blockquote
const inBlockquote = editor.nodes.blockquote.isActive()

// Wrap selection in blockquote
if (!inBlockquote) {
  editor.commands.setBlockquote()
}

// Toggle blockquote
editor.commands.toggleBlockquote()

Nested Blockquotes

Blockquotes can be nested within other blockquotes:
// Type this in the editor:
> First level quote
> > Nested quote

Styling

Blockquote nodes render as standard <blockquote> HTML elements:
.prosekit-editor blockquote {
  border-left: 3px solid #e5e7eb;
  padding-left: 1rem;
  margin: 1rem 0;
  color: #6b7280;
  font-style: italic;
}

.prosekit-editor blockquote > *:first-child {
  margin-top: 0;
}

.prosekit-editor blockquote > *:last-child {
  margin-bottom: 0;
}

/* Nested blockquotes */
.prosekit-editor blockquote blockquote {
  margin: 0.5rem 0;
}

HTML Structure

Input HTML:
<blockquote>
  <p>This is a quoted text.</p>
</blockquote>
Output HTML:
<blockquote>
  <p>This is a quoted text.</p>
</blockquote>
Nested blockquotes:
<blockquote>
  <p>Outer quote</p>
  <blockquote>
    <p>Nested quote</p>
  </blockquote>
</blockquote>

Use Cases

  • Citing external sources
  • Highlighting important quotes
  • Displaying testimonials
  • Showing excerpts from other documents
  • Creating visual emphasis for specific content

Accessibility

Blockquote elements are semantic HTML and are properly recognized by screen readers:
  • Screen readers announce blockquote boundaries
  • Consider adding cite attribute for source attribution
  • Use clear visual styling to distinguish quotes from regular text
  • Paragraph - Contains text within blockquotes
  • Heading - Can be used inside blockquotes
  • Text - Required for text content