or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

delta-operations.mdeditor-core.mdformatting-system.mdindex.mdmodule-system.mdregistry-system.mdtheme-system.md
tile.json

tessl/npm-quill

A modern, powerful rich text editor built for compatibility and extensibility

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/quill@2.0.x

To install, run

npx @tessl/cli install tessl/npm-quill@2.0.0

index.mddocs/

Quill

Quill is a modern, powerful rich text editor built for compatibility and extensibility. It provides a comprehensive WYSIWYG editing experience with support for operational transformation, custom formatting, modular architecture, and extensive theming capabilities. The library offers both programmatic API access and user-friendly toolbar interfaces, supports multiple output formats including Delta (its native format), HTML, and plain text, and includes built-in modules for clipboard handling, keyboard shortcuts, history/undo-redo functionality, and toolbar management.

Package Information

  • Package Name: quill
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install quill

Core Imports

import Quill from "quill";

For CommonJS:

const Quill = require("quill");

Basic Usage

import Quill from "quill";

// Initialize Quill editor
const quill = new Quill('#editor', {
  theme: 'snow',
  modules: {
    toolbar: [
      ['bold', 'italic', 'underline'],
      ['link', 'image'],
      [{ 'header': [1, 2, 3, false] }],
      [{ 'list': 'ordered'}, { 'list': 'bullet' }]
    ]
  }
});

// Get/set content
const content = quill.getContents();
quill.setContents(content);

// Listen for changes
quill.on('text-change', (delta, oldDelta, source) => {
  console.log('Text changed:', delta);
});

Architecture

Quill is built around several key components:

  • Delta System: Operational transform-based document representation using Delta format for change tracking
  • Blot System: Parchment-based document model where content is represented as structured blots (blocks, inlines, embeds)
  • Module Architecture: Extensible plugin system with core modules (History, Keyboard, Clipboard, Toolbar)
  • Theme System: UI layer providing Snow (toolbar above) and Bubble (floating toolbar) themes
  • Event System: Comprehensive event emission for text changes, selection changes, and editor interactions
  • Format Registry: Dynamic registration system for custom formats, blots, modules, and themes

Capabilities

Editor Core

Core editor functionality for creating and managing rich text editor instances. The main Quill class provides all essential editing operations.

class Quill {
  constructor(container: HTMLElement | string, options?: QuillOptions);
  
  // Content operations
  getContents(index?: number, length?: number): Delta;
  setContents(delta: Delta | Op[], source?: EmitterSource): Delta;
  updateContents(delta: Delta | Op[], source?: EmitterSource): Delta;
  getText(index?: number, length?: number): string;
  setText(text: string, source?: EmitterSource): Delta;
  getSemanticHTML(range: Range): string;
  getSemanticHTML(index?: number, length?: number): string;
  
  // Selection operations
  getSelection(focus?: boolean): Range | null;
  setSelection(range: Range | null, source?: EmitterSource): void;
  setSelection(index: number, length?: number, source?: EmitterSource): void;
  getBounds(index: number | Range, length?: number): Bounds | null;
  
  // Formatting operations
  format(name: string, value: unknown, source?: EmitterSource): Delta;
  formatText(index: number, length: number, formats: Record<string, unknown>, source?: EmitterSource): Delta;
  formatLine(index: number, length: number, formats: Record<string, unknown>, source?: EmitterSource): Delta;
  removeFormat(index: number, length: number, source?: EmitterSource): Delta;
  getFormat(index?: number, length?: number): { [format: string]: unknown };
  
  // Text operations
  insertText(index: number, text: string, formats?: Record<string, unknown>, source?: EmitterSource): Delta;
  insertEmbed(index: number, embed: string, value: unknown, source?: EmitterSource): Delta;
  deleteText(index: number, length: number, source?: EmitterSource): Delta;
  
  // Editor state
  focus(options?: { preventScroll?: boolean }): void;
  blur(): void;
  enable(enabled?: boolean): void;
  disable(): void;
  isEnabled(): boolean;
  hasFocus(): boolean;
  
  // Event handling
  on(event: string, handler: (...args: any[]) => void): Emitter;
  off(event: string, handler?: (...args: any[]) => void): Emitter;
  once(event: string, handler: (...args: any[]) => void): Emitter;
  
  // Additional content methods
  getIndex(blot: Parchment.Blot): number;
  getLeaf(index: number): [Parchment.Leaf | null, number];
  getLine(index: number): [Parchment.Block | Parchment.BlockEmbed | null, number];
  getLines(index?: number, length?: number): (Parchment.Block | Parchment.BlockEmbed)[];
  getLines(range: Range): (Parchment.Block | Parchment.BlockEmbed)[];
  
  // Container management
  addContainer(container: string, refNode?: Node | null): HTMLDivElement;
  addContainer(container: HTMLElement, refNode?: Node | null): HTMLElement;
  
  // Advanced editing
  editReadOnly<T>(modifier: () => T): T;
  scrollRectIntoView(rect: { top: number; left: number; right: number; bottom: number }): void;
  
  // Deprecated methods
  scrollIntoView(): void; // @deprecated Use scrollSelectionIntoView()
  
  // Utility methods
  getLength(): number;
  getModule(name: string): Module;
  scrollSelectionIntoView(): void;
  update(source?: EmitterSource): Delta | undefined;
  // Static methods
  static debug(level: DebugLevel | boolean): void;
  static find(node: Node, bubble?: boolean): Parchment.Blot | null;
  static import(name: string): unknown;
  static register(path: string, target: any, overwrite?: boolean): void;
  static register(target: Record<string, any>, overwrite?: boolean): void;
  static register(target: Parchment.RegistryDefinition, overwrite?: boolean): void;
  
  // Static properties
  static DEFAULTS: Partial<QuillOptions>;
  static events: typeof Emitter.events;
  static sources: typeof Emitter.sources;
  static version: string;
}

interface QuillOptions {
  theme?: string;
  debug?: DebugLevel | boolean;
  registry?: Parchment.Registry;
  readOnly?: boolean;
  placeholder?: string;
  bounds?: HTMLElement | string | null;
  modules?: Record<string, unknown>;
  formats?: string[] | null;
}

interface Range {
  index: number;
  length: number;
}

interface Bounds {
  bottom: number;
  height: number;
  left: number;
  right: number;
  top: number;
  width: number;
}

type EmitterSource = 'api' | 'user' | 'silent';
type DebugLevel = 'error' | 'warn' | 'log' | 'info';

interface Emitter {
  on(event: string, handler: (...args: any[]) => void): Emitter;
  off(event: string, handler?: (...args: any[]) => void): Emitter;
  once(event: string, handler: (...args: any[]) => void): Emitter;
  emit(event: string, ...args: any[]): void;
}

namespace Emitter {
  const events = {
    TEXT_CHANGE: 'text-change',
    SELECTION_CHANGE: 'selection-change',
    EDITOR_CHANGE: 'editor-change'
  };
  const sources = {
    API: 'api' as EmitterSource,
    USER: 'user' as EmitterSource,
    SILENT: 'silent' as EmitterSource
  };
}

Editor Core

Delta Operations

Delta-based document representation and operational transform system for tracking and applying changes to rich text content.

class Delta {
  constructor(ops?: Op[] | Delta);
  
  // Core operations
  insert(text: string, attributes?: AttributeMap): Delta;
  insert(embed: object, attributes?: AttributeMap): Delta;
  delete(length: number): Delta;
  retain(length: number, attributes?: AttributeMap): Delta;
  
  // Delta manipulation
  compose(other: Delta): Delta;
  transform(other: Delta, priority?: boolean): Delta;
  transformPosition(index: number, priority?: boolean): number;
  diff(other: Delta, cursor?: number): Delta;
  
  // Utility methods
  length(): number;
  slice(start?: number, end?: number): Delta;
  partition(predicate: (op: Op) => boolean): [Delta, Delta];
  filter(predicate: (op: Op, index: number) => boolean): Op[];
  forEach(predicate: (op: Op, index: number) => void): void;
  map<T>(predicate: (op: Op, index: number) => T): T[];
  reduce<T>(predicate: (acc: T, curr: Op, index: number) => T, initialValue: T): T;
}

interface Op {
  insert?: string | object;
  delete?: number;
  retain?: number;
  attributes?: AttributeMap;
}

interface AttributeMap {
  [key: string]: unknown;
}

Delta Operations

Formatting System

Comprehensive formatting system supporting inline formats (bold, italic, links), block formats (headers, lists, blockquotes), and custom attributors.

// Built-in inline formats
class Bold extends Inline {
  static blotName: 'bold';
  static tagName: ['STRONG', 'B'];
}

class Italic extends Inline {
  static blotName: 'italic';
  static tagName: ['EM', 'I'];
}

class Link extends Inline {
  static blotName: 'link';
  static tagName: 'A';
  static create(value: string): HTMLAnchorElement;
  static formats(domNode: HTMLAnchorElement): string;
  static sanitize(url: string): string;
}

// Built-in block formats
class Header extends Block {
  static blotName: 'header';
  static tagName: ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
  static formats(domNode: HTMLElement): number;
}

class List extends Block {
  static blotName: 'list';
  static tagName: 'LI';
  static create(value: 'ordered' | 'bullet'): HTMLLIElement;
  static formats(domNode: HTMLLIElement): string;
}

// Embed formats
class Image extends EmbedBlot {
  static blotName: 'image';
  static tagName: 'IMG';
  static create(value: string): HTMLImageElement;
  static formats(domNode: HTMLImageElement): Record<string, string>;
  static value(domNode: HTMLImageElement): string;
}

Formatting System

Module System

Extensible module architecture with core modules for history, keyboard, clipboard, toolbar, and upload functionality.

abstract class Module {
  static DEFAULTS: Record<string, unknown>;
  constructor(quill: Quill, options?: Record<string, unknown>);
}

class History extends Module {
  static DEFAULTS: {
    delay: number;
    maxStack: number;
    userOnly: boolean;
  };
  
  clear(): void;
  cutoff(): void;
  undo(): void;
  redo(): void;
}

class Toolbar extends Module {
  static DEFAULTS: {
    container?: string | HTMLElement | (string | Record<string, unknown>)[];
    handlers?: Record<string, ToolbarHandler>;
  };
  
  addHandler(format: string, handler: ToolbarHandler): void;
  attach(input: HTMLElement): void;
  update(range: Range | null): void;
}

class Clipboard extends Module {
  addMatcher(selector: string, matcher: ClipboardMatcher): void;
  dangerouslyPasteHTML(html: string, source?: EmitterSource): void;
  convert(clipboard: { html?: string; text?: string }): Delta;
}

type ToolbarHandler = (value: unknown) => void;
type ClipboardMatcher = (node: Node, delta: Delta) => Delta;

Module System

Theme System

Theme system providing Snow and Bubble themes with customizable UI components and toolbar layouts.

abstract class Theme {
  static DEFAULTS: Record<string, unknown>;
  constructor(quill: Quill, options: Record<string, unknown>);
  
  init(): void;
  addModule(name: string): Module;
}

class SnowTheme extends Theme {
  // Snow theme with toolbar above editor
}

class BubbleTheme extends Theme {
  // Bubble theme with floating toolbar
}

Theme System

Registry System

Dynamic registration system for formats, modules, themes, and blots enabling extensibility and customization.

class Quill {
  static register(path: string, target: any, overwrite?: boolean): void;
  static register(target: Record<string, any>, overwrite?: boolean): void;
  static register(target: RegistryDefinition, overwrite?: boolean): void;
  
  static import(name: string): unknown;
  static find(node: Node, bubble?: boolean): Blot | null;
  static debug(level: DebugLevel | boolean): void;
}

// Registration paths
// 'formats/bold' - Register Bold format
// 'modules/toolbar' - Register Toolbar module  
// 'themes/snow' - Register Snow theme
// 'blots/block' - Register Block blot
// 'attributors/style/color' - Register style-based color attributor

Registry System

Types

// Re-exported from quill-delta
interface Delta {
  ops: Op[];
}

interface Op {
  insert?: string | object;
  delete?: number;
  retain?: number;
  attributes?: AttributeMap;
}

interface AttributeMap {
  [key: string]: unknown;
}

class OpIterator {
  constructor(ops: Op[]);
  hasNext(): boolean;
  next(length?: number): Op;
  peek(): Op;
  peekLength(): number;
  peekType(): 'insert' | 'delete' | 'retain';
  rest(): Op[];
}

// Re-exported from parchment
namespace Parchment {
  abstract class Blot {
    static blotName: string;
    static className?: string;
    static tagName?: string | string[];
    static scope: Scope;
    
    domNode: Node;
    parent: Blot | null;
    prev: Blot | null;
    next: Blot | null;
    
    constructor(scroll: ScrollBlot, domNode?: Node);
    
    attach(): void;
    clone(): Blot;
    detach(): void;
    deleteAt(index: number, length: number): void;
    formatAt(index: number, length: number, name: string, value: any): void;
    insertAt(index: number, value: string, def?: any): void;
    isolate(index: number, length: number): Blot;
    length(): number;
    offset(root?: Blot): number;
    optimize(context: any): void;
    remove(): void;
    replaceWith(name: string | Blot, value?: any): Blot;
    split(index: number, force?: boolean): Blot | null;
    update(mutations: MutationRecord[], context: any): void;
    wrap(name: string | Blot, value?: any): Blot;
  }
  
  enum Scope {
    TYPE = 3,
    LEVEL = 12,
    ATTRIBUTE = 13,
    BLOT = 14,
    INLINE = 7,
    BLOCK = 11,
    BLOCK_BLOT = 10,
    INLINE_BLOT = 6,
    LEAF = 4,
    PARENT = 8,
    ANY = 15
  }
  
  class Registry {
    create(scroll: ScrollBlot, input: Node | string | Scope, value?: any): Blot;
    find(domNode: Node, bubble?: boolean): Blot | null;
    query(query: string | Node | Scope, scope?: Scope): BlotConstructor | null;
    register(...definitions: RegistryDefinition[]): void;
  }
}