or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

formatting-system.mddocs/

0

# Formatting System

1

2

Comprehensive formatting system supporting inline formats (bold, italic, links), block formats (headers, lists, blockquotes), embed formats (images, videos), and custom attributors for style-based formatting. Quill's formatting system is built on Parchment blots that map directly to DOM elements.

3

4

## Capabilities

5

6

### Inline Formats

7

8

Text-level formatting that can be applied to character ranges within a line.

9

10

```typescript { .api }

11

// Bold formatting

12

class Bold extends Inline {

13

static blotName: 'bold';

14

static tagName: ['STRONG', 'B'];

15

}

16

17

// Italic formatting

18

class Italic extends Inline {

19

static blotName: 'italic';

20

static tagName: ['EM', 'I'];

21

}

22

23

// Underline formatting

24

class Underline extends Inline {

25

static blotName: 'underline';

26

static tagName: 'U';

27

}

28

29

// Strikethrough formatting

30

class Strike extends Inline {

31

static blotName: 'strike';

32

static tagName: ['S', 'STRIKE'];

33

}

34

35

// Inline code formatting

36

class Code extends Inline {

37

static blotName: 'code';

38

static tagName: 'CODE';

39

}

40

41

// Superscript/subscript formatting

42

class Script extends Inline {

43

static blotName: 'script';

44

static tagName: ['SUB', 'SUP'];

45

static create(value: 'sub' | 'super'): HTMLElement;

46

static formats(domNode: HTMLElement): string;

47

}

48

```

49

50

**Usage Examples:**

51

52

```typescript

53

// Apply inline formatting

54

quill.formatText(0, 5, 'bold', true);

55

quill.formatText(6, 4, 'italic', true);

56

quill.formatText(11, 3, 'underline', true);

57

quill.formatText(15, 6, 'strike', true);

58

quill.formatText(22, 4, 'code', true);

59

quill.formatText(27, 4, 'script', 'super');

60

61

// Multiple formats at once

62

quill.formatText(0, 10, {

63

bold: true,

64

italic: true,

65

color: '#ff0000'

66

});

67

68

// Remove formatting

69

quill.formatText(0, 10, {

70

bold: false,

71

italic: null // null also removes formatting

72

});

73

```

74

75

### Link Format

76

77

Hyperlink formatting with URL validation and sanitization.

78

79

```typescript { .api }

80

class Link extends Inline {

81

static blotName: 'link';

82

static tagName: 'A';

83

static SANITIZED_URL: 'about:blank';

84

static PROTOCOL_WHITELIST: ['http', 'https', 'mailto', 'tel', 'sms'];

85

86

/**

87

* Create link element with href attribute

88

* @param value - URL for the link

89

* @returns HTMLAnchorElement with href set

90

*/

91

static create(value: string): HTMLAnchorElement;

92

93

/**

94

* Get href value from link element

95

* @param domNode - Link element

96

* @returns URL from href attribute

97

*/

98

static formats(domNode: HTMLAnchorElement): string;

99

100

/**

101

* Sanitize URL to prevent XSS attacks

102

* @param url - URL to sanitize

103

* @returns Sanitized URL or fallback URL

104

*/

105

static sanitize(url: string): string;

106

107

/**

108

* Format this link blot

109

* @param name - Format name ('link')

110

* @param value - URL value or false to remove link

111

*/

112

format(name: string, value: string | boolean): void;

113

}

114

115

/**

116

* Standalone URL sanitization function

117

* @param url - URL to sanitize

118

* @param protocols - Allowed protocols (default: Link.PROTOCOL_WHITELIST)

119

* @returns Sanitized URL

120

*/

121

function sanitize(url: string, protocols?: string[]): string;

122

```

123

124

**Usage Examples:**

125

126

```typescript

127

// Create links

128

quill.formatText(0, 5, 'link', 'https://example.com');

129

quill.formatText(10, 8, 'link', 'mailto:user@example.com');

130

quill.formatText(20, 12, 'link', 'tel:+1234567890');

131

132

// Get current link value

133

const formats = quill.getFormat(5, 0);

134

if (formats.link) {

135

console.log('Link URL:', formats.link);

136

}

137

138

// Remove link

139

quill.formatText(0, 5, 'link', false);

140

141

// Insert link with text

142

quill.insertText(0, 'Click here', { link: 'https://example.com' });

143

```

144

145

### Block Formats

146

147

Line-level formatting that affects entire lines or paragraphs.

148

149

```typescript { .api }

150

// Header formatting (H1-H6)

151

class Header extends Block {

152

static blotName: 'header';

153

static tagName: ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];

154

155

/**

156

* Get header level from DOM element

157

* @param domNode - Header element

158

* @returns Header level (1-6)

159

*/

160

static formats(domNode: HTMLElement): number;

161

162

/**

163

* Create header element for specified level

164

* @param value - Header level (1-6)

165

* @returns Header element

166

*/

167

static create(value: number): HTMLElement;

168

}

169

170

// Blockquote formatting

171

class Blockquote extends Block {

172

static blotName: 'blockquote';

173

static tagName: 'blockquote';

174

}

175

176

// Code block formatting

177

class CodeBlock extends Block {

178

static blotName: 'code-block';

179

static tagName: 'DIV';

180

static className: 'ql-code-block';

181

static TAB: string;

182

183

/**

184

* Handle tab key in code blocks

185

* @param range - Current selection range

186

* @param context - Keyboard context

187

*/

188

static handleTab(range: Range, context: any): boolean;

189

}

190

```

191

192

**Usage Examples:**

193

194

```typescript

195

// Apply block formatting

196

quill.formatLine(0, 1, 'header', 1); // H1

197

quill.formatLine(20, 1, 'header', 2); // H2

198

quill.formatLine(40, 1, 'blockquote', true);

199

quill.formatLine(60, 1, 'code-block', true);

200

201

// Multiple lines

202

quill.formatLine(0, 50, 'header', 3); // Format multiple lines as H3

203

204

// Remove block formatting

205

quill.formatLine(0, 1, 'header', false);

206

quill.formatLine(20, 1, 'blockquote', false);

207

```

208

209

### List Formats

210

211

Ordered and unordered list formatting with nested list support.

212

213

```typescript { .api }

214

// List item formatting

215

class ListItem extends Block {

216

static blotName: 'list';

217

static tagName: 'LI';

218

219

/**

220

* Create list item element

221

* @param value - List type ('ordered' | 'bullet')

222

* @returns List item element

223

*/

224

static create(value: 'ordered' | 'bullet'): HTMLLIElement;

225

226

/**

227

* Get list type from DOM element

228

* @param domNode - List item element

229

* @returns List type string

230

*/

231

static formats(domNode: HTMLLIElement): string;

232

233

/**

234

* Register list container with Parchment

235

*/

236

static register(): void;

237

238

/**

239

* Format this list item

240

* @param name - Format name

241

* @param value - Format value

242

*/

243

format(name: string, value: any): void;

244

}

245

246

// List container formatting

247

class ListContainer extends Container {

248

static blotName: 'list-container';

249

static tagName: 'OL';

250

251

/**

252

* Create list container element

253

* @param value - List type

254

* @returns List container element

255

*/

256

static create(value: string): HTMLOListElement | HTMLUListElement;

257

}

258

```

259

260

**Usage Examples:**

261

262

```typescript

263

// Create bullet list

264

quill.formatLine(0, 1, 'list', 'bullet');

265

quill.formatLine(20, 1, 'list', 'bullet');

266

quill.formatLine(40, 1, 'list', 'bullet');

267

268

// Create ordered list

269

quill.formatLine(0, 1, 'list', 'ordered');

270

quill.formatLine(20, 1, 'list', 'ordered');

271

quill.formatLine(40, 1, 'list', 'ordered');

272

273

// Remove list formatting

274

quill.formatLine(0, 1, 'list', false);

275

276

// Insert list items

277

quill.insertText(0, 'First item\n', { list: 'bullet' });

278

quill.insertText(11, 'Second item\n', { list: 'bullet' });

279

```

280

281

### Embed Formats

282

283

Self-contained elements like images, videos, and formulas.

284

285

```typescript { .api }

286

// Image embed

287

class Image extends EmbedBlot {

288

static blotName: 'image';

289

static tagName: 'IMG';

290

291

/**

292

* Create image element

293

* @param value - Image URL or configuration object

294

* @returns Image element

295

*/

296

static create(value: string | { src: string; alt?: string; [key: string]: any }): HTMLImageElement;

297

298

/**

299

* Get image attributes

300

* @param domNode - Image element

301

* @returns Object with image attributes

302

*/

303

static formats(domNode: HTMLImageElement): Record<string, string>;

304

305

/**

306

* Check if URL is valid image

307

* @param url - URL to check

308

* @returns True if URL appears to be an image

309

*/

310

static match(url: string): boolean;

311

312

/**

313

* Sanitize image URL

314

* @param url - URL to sanitize

315

* @returns Sanitized URL

316

*/

317

static sanitize(url: string): string;

318

319

/**

320

* Get image source URL

321

* @param domNode - Image element

322

* @returns Image source URL

323

*/

324

static value(domNode: HTMLImageElement): string;

325

326

/**

327

* Format image attributes

328

* @param name - Attribute name

329

* @param value - Attribute value

330

*/

331

format(name: string, value: any): void;

332

}

333

334

// Video embed

335

class Video extends BlockEmbed {

336

static blotName: 'video';

337

static tagName: 'IFRAME';

338

static ATTRIBUTES: string[];

339

340

/**

341

* Create video iframe element

342

* @param value - Video URL

343

* @returns Iframe element

344

*/

345

static create(value: string): HTMLIFrameElement;

346

347

/**

348

* Get video URL from iframe

349

* @param domNode - Iframe element

350

* @returns Video URL

351

*/

352

static formats(domNode: HTMLIFrameElement): string;

353

354

/**

355

* Sanitize video URL

356

* @param url - URL to sanitize

357

* @returns Sanitized URL

358

*/

359

static sanitize(url: string): string;

360

361

/**

362

* Get video URL value

363

* @param domNode - Iframe element

364

* @returns Video URL

365

*/

366

static value(domNode: HTMLIFrameElement): string;

367

}

368

369

// Formula embed (for mathematical expressions)

370

class Formula extends EmbedBlot {

371

static blotName: 'formula';

372

static tagName: 'SPAN';

373

static className: 'ql-formula';

374

375

/**

376

* Create formula element

377

* @param value - LaTeX formula string

378

* @returns Span element with formula

379

*/

380

static create(value: string): HTMLSpanElement;

381

382

/**

383

* Get formula value

384

* @param domNode - Formula element

385

* @returns LaTeX formula string

386

*/

387

static value(domNode: HTMLSpanElement): string;

388

389

/**

390

* Render formula (requires KaTeX or similar)

391

* @param value - LaTeX formula

392

* @returns Rendered formula HTML

393

*/

394

html(): string;

395

}

396

```

397

398

**Usage Examples:**

399

400

```typescript

401

// Insert image

402

quill.insertEmbed(0, 'image', 'https://example.com/image.jpg');

403

404

// Insert image with attributes

405

quill.insertEmbed(0, 'image', {

406

src: 'https://example.com/image.jpg',

407

alt: 'Example image',

408

width: '300'

409

});

410

411

// Insert video

412

quill.insertEmbed(10, 'video', 'https://youtube.com/watch?v=abc123');

413

414

// Insert formula

415

quill.insertEmbed(20, 'formula', 'E = mc^2');

416

417

// Get embed values

418

const delta = quill.getContents();

419

delta.ops.forEach(op => {

420

if (op.insert && typeof op.insert === 'object') {

421

if (op.insert.image) {

422

console.log('Image URL:', op.insert.image);

423

} else if (op.insert.video) {

424

console.log('Video URL:', op.insert.video);

425

} else if (op.insert.formula) {

426

console.log('Formula:', op.insert.formula);

427

}

428

}

429

});

430

```

431

432

### Attributor-Based Formats

433

434

Style-based formatting using CSS classes or inline styles.

435

436

```typescript { .api }

437

// Color attributor (style-based)

438

class ColorStyle extends StyleAttributor {

439

static attrName: 'color';

440

static keyName: 'color';

441

static styleName: 'color';

442

}

443

444

// Color attributor (class-based)

445

class ColorClass extends ClassAttributor {

446

static attrName: 'color';

447

static keyName: 'color';

448

static className: 'ql-color';

449

}

450

451

// Font attributor

452

class FontClass extends ClassAttributor {

453

static attrName: 'font';

454

static keyName: 'font';

455

static className: 'ql-font';

456

}

457

458

class FontStyle extends StyleAttributor {

459

static attrName: 'font';

460

static keyName: 'font';

461

static styleName: 'font-family';

462

}

463

464

// Size attributor

465

class SizeClass extends ClassAttributor {

466

static attrName: 'size';

467

static keyName: 'size';

468

static className: 'ql-size';

469

}

470

471

class SizeStyle extends StyleAttributor {

472

static attrName: 'size';

473

static keyName: 'size';

474

static styleName: 'font-size';

475

}

476

477

// Background attributor

478

class BackgroundClass extends ClassAttributor {

479

static attrName: 'background';

480

static keyName: 'background';

481

static className: 'ql-bg';

482

}

483

484

class BackgroundStyle extends StyleAttributor {

485

static attrName: 'background';

486

static keyName: 'background';

487

static styleName: 'background-color';

488

}

489

490

// Alignment attributor

491

class AlignClass extends ClassAttributor {

492

static attrName: 'align';

493

static keyName: 'align';

494

static className: 'ql-align';

495

}

496

497

class AlignStyle extends StyleAttributor {

498

static attrName: 'align';

499

static keyName: 'align';

500

static styleName: 'text-align';

501

}

502

503

// Direction attributor

504

class DirectionAttribute extends AttributeAttributor {

505

static attrName: 'direction';

506

static keyName: 'direction';

507

static htmlAttribute: 'dir';

508

}

509

510

class DirectionClass extends ClassAttributor {

511

static attrName: 'direction';

512

static keyName: 'direction';

513

static className: 'ql-direction';

514

}

515

516

class DirectionStyle extends StyleAttributor {

517

static attrName: 'direction';

518

static keyName: 'direction';

519

static styleName: 'direction';

520

}

521

522

// Indent attributor

523

class Indent extends ClassAttributor {

524

static attrName: 'indent';

525

static keyName: 'indent';

526

static className: 'ql-indent';

527

528

/**

529

* Add value to current indent level

530

* @param node - DOM node

531

* @param value - Indent level to add

532

*/

533

add(node: HTMLElement, value: number): void;

534

535

/**

536

* Compute new indent level

537

* @param value - Current indent level

538

* @param delta - Change in indent level

539

* @returns New indent level

540

*/

541

canAdd(value: number, delta: number): boolean;

542

543

/**

544

* Remove indent level

545

* @param node - DOM node

546

*/

547

remove(node: HTMLElement): void;

548

549

/**

550

* Get current indent value

551

* @param node - DOM node

552

* @returns Current indent level

553

*/

554

value(node: HTMLElement): number;

555

}

556

```

557

558

**Usage Examples:**

559

560

```typescript

561

// Apply color formatting

562

quill.formatText(0, 10, 'color', '#ff0000');

563

quill.formatText(15, 5, 'background', '#ffff00');

564

565

// Apply font formatting

566

quill.formatText(0, 10, 'font', 'serif');

567

quill.formatText(15, 5, 'size', 'large');

568

569

// Apply alignment

570

quill.formatLine(0, 1, 'align', 'center');

571

quill.formatLine(20, 1, 'align', 'right');

572

573

// Apply direction

574

quill.formatLine(0, 1, 'direction', 'rtl');

575

576

// Apply indentation

577

quill.formatLine(0, 1, 'indent', 1); // Indent once

578

quill.formatLine(20, 1, 'indent', 2); // Indent twice

579

580

// Remove attributor formatting

581

quill.formatText(0, 10, 'color', false);

582

quill.formatLine(0, 1, 'align', false);

583

```

584

585

### Custom Format Registration

586

587

Register custom formats and blots with Quill.

588

589

```typescript { .api }

590

// Register custom formats

591

Quill.register('formats/highlight', HighlightBlot);

592

Quill.register('formats/mention', MentionBlot);

593

594

// Register multiple formats

595

Quill.register({

596

'formats/highlight': HighlightBlot,

597

'formats/mention': MentionBlot,

598

'attributors/style/custom': CustomStyleAttributor

599

});

600

601

// Register with overwrite option

602

Quill.register('formats/bold', CustomBoldBlot, true);

603

```

604

605

**Usage Examples:**

606

607

```typescript

608

// Define custom highlight format

609

class Highlight extends Inline {

610

static blotName = 'highlight';

611

static tagName = 'MARK';

612

static className = 'ql-highlight';

613

614

static create(value) {

615

const node = super.create();

616

node.setAttribute('data-color', value);

617

node.style.backgroundColor = value;

618

return node;

619

}

620

621

static formats(node) {

622

return node.getAttribute('data-color');

623

}

624

}

625

626

// Register and use

627

Quill.register('formats/highlight', Highlight);

628

629

const quill = new Quill('#editor', {

630

formats: ['bold', 'italic', 'highlight']

631

});

632

633

// Use custom format

634

quill.formatText(0, 10, 'highlight', 'yellow');

635

```

636

637

## Table Formats

638

639

Table formatting system for creating and managing tabular data with cells, rows, and full table structures.

640

641

### Table Structure

642

643

Tables in Quill follow a hierarchical structure: TableContainer > TableBody > TableRow > TableCell.

644

645

### TableCell

646

647

Individual table cell format for containing content within table rows.

648

649

```typescript { .api }

650

class TableCell extends Block {

651

static blotName: 'table';

652

static tagName: 'TD';

653

static create(value?: string): HTMLTableCellElement;

654

static formats(domNode: HTMLElement): string | undefined;

655

656

cellOffset(): number;

657

format(name: string, value: string): void;

658

row(): TableRow;

659

rowOffset(): number;

660

table(): TableContainer | null;

661

}

662

```

663

664

### TableRow

665

666

Table row format for containing table cells in a horizontal layout.

667

668

```typescript { .api }

669

class TableRow extends Container {

670

static blotName: 'table-row';

671

static tagName: 'TR';

672

673

checkMerge(): boolean;

674

optimize(context: { [key: string]: any }): void;

675

rowOffset(): number;

676

table(): TableContainer | null;

677

}

678

```

679

680

### TableBody

681

682

Table body format for containing table rows within a table structure.

683

684

```typescript { .api }

685

class TableBody extends Container {

686

static blotName: 'table-body';

687

static tagName: 'TBODY';

688

}

689

```

690

691

### TableContainer

692

693

Main table container format providing table manipulation methods and structure management.

694

695

```typescript { .api }

696

class TableContainer extends Container {

697

static blotName: 'table-container';

698

static tagName: 'TABLE';

699

700

balanceCells(): void;

701

cells(column: number): (TableCell | null)[];

702

deleteColumn(index: number): void;

703

insertColumn(index: number): void;

704

insertRow(index: number): void;

705

rows(): TableRow[];

706

}

707

```

708

709

**Usage Examples:**

710

711

```typescript

712

import { TableCell, TableRow, TableBody, TableContainer } from 'quill';

713

714

// Tables are typically created through the module system

715

// rather than direct format application

716

const quill = new Quill('#editor', {

717

modules: {

718

table: true

719

}

720

});

721

722

// Use table module methods for table manipulation

723

const tableModule = quill.getModule('table');

724

tableModule.insertTable(3, 3); // 3x3 table

725

```