The Rich Text Editor
Angular Deserves
Toolbar, bubble menu, tables, code blocks, image upload, and more. One package, import only what you need, your bundler tree-shakes the rest.
React and Vue components also available. Or use the headless core with any framework.
npm i @domternal/core @domternal/angular @domternal/theme Try it yourself
Get started in minutes
A few lines of code is all you need
import { Component, signal } from '@angular/core'; import { DomternalEditorComponent, DomternalToolbarComponent, DomternalBubbleMenuComponent, } from '@domternal/angular'; import { Editor, StarterKit, BubbleMenu } from '@domternal/core'; @Component({ selector: 'app-editor', imports: [DomternalEditorComponent, DomternalToolbarComponent, DomternalBubbleMenuComponent], template: ` @if (editor(); as ed) { <domternal-toolbar [editor]="ed" /> } <domternal-editor [extensions]="extensions" [content]="content" (editorCreated)="editor.set($event)" /> @if (editor(); as ed) { <domternal-bubble-menu [editor]="ed" /> } ` }) export class EditorComponent { editor = signal<Editor | null>(null); extensions = [StarterKit, BubbleMenu]; content = '<p>Hello from Angular!</p>'; }
import { Domternal } from '@domternal/react'; import { StarterKit, BubbleMenu } from '@domternal/core'; export default function Editor() { return ( <Domternal extensions={[StarterKit, BubbleMenu]} content="<p>Hello from React!</p>" > <Domternal.Toolbar /> <Domternal.Content /> <Domternal.BubbleMenu /> </Domternal> ); }
<script setup> import { Domternal } from '@domternal/vue'; import { StarterKit, BubbleMenu } from '@domternal/core'; const extensions = [StarterKit, BubbleMenu]; </script> <template> <Domternal :extensions="extensions" content="<p>Hello from Vue!</p>" > <Domternal.Toolbar /> <Domternal.Content /> <Domternal.BubbleMenu /> </Domternal> </template>
import { Editor, Document, Text, Paragraph, Bold, Italic, Underline, } from '@domternal/core'; new Editor({ element: document.getElementById('editor')!, extensions: [Document, Text, Paragraph, Bold, Italic, Underline], content: '<p>Hello <strong>Bold</strong>, <em>Italic</em> and <u>Underline</u>!</p>', });
import { Editor, StarterKit, defaultIcons } from '@domternal/core'; import '@domternal/theme'; const editorEl = document.getElementById('editor')!; // Toolbar const toolbar = document.createElement('div'); toolbar.className = 'dm-toolbar'; toolbar.innerHTML = `<div class="dm-toolbar-group"> <button class="dm-toolbar-button" data-mark="bold">${defaultIcons.textB}</button> <button class="dm-toolbar-button" data-mark="italic">${defaultIcons.textItalic}</button> <button class="dm-toolbar-button" data-mark="underline">${defaultIcons.textUnderline}</button> </div>`; editorEl.before(toolbar); // Editor const editor = new Editor({ element: editorEl, extensions: [StarterKit], content: '<p>Hello world</p>', }); // Toggle marks on click toolbar.addEventListener('click', (e) => { const btn = (e.target as Element).closest<HTMLButtonElement>('[data-mark]'); if (!btn) return; editor.chain().focus().toggleMark(btn.dataset.mark!).run(); });
Everything you need to build
rich editing experiences
A complete editor framework with full control over every aspect of your editor.
57 Built-in Extensions
23 nodes, 9 marks, 25 extensions across 12 packages. Tables, images, emoji, mentions, details, syntax highlighting. Everything included.
Angular-First
5 components: editor, toolbar, bubble menu, floating menu, emoji picker. Signals, OnPush, ControlValueAccessor. Built for modern Angular.
Built-in Toolbar & Theme
Every extension declares toolbar items via addToolbarItems(). 45 Phosphor icons included. Light & dark theme with CSS custom properties. Ready to customize.
Styled HTML Export
getHTML({ styled: true }) produces inline CSS ready for email clients, CMS, and Google Docs. Customizable styles for tables, blockquotes, code blocks, and more.
Markdown-Style Shortcuts
Type ## for heading, > for blockquote, - for list, **bold**, ==highlight==, --- for rule. Every extension registers its own input rules.
8,500+ Tests
2,677 unit tests across 92 files. 5,800+ Playwright E2E tests across 120+ specs. Every extension, mark, and node is tested.
Full table support,
Angular & Vanilla JS
- Cell merge & split (colspan/rowspan)
- 3 resize modes: neighbor, independent, redistribute
- constrainToContainer: lock or free table width
- Cell background, alignment, vertical align
- Export-ready: percent, pixel, or no column widths
- Floating cell toolbar on selection
- 18 table commands, 400+ tests
| Feature | Q1 | Q2 | Q3 |
|---|---|---|---|
| Editor Core | Released | Stable | Stable |
| Tables | Released | Stable | Stable |
| Theme | Light + Dark (Merged Cell) | ||
| Angular | 5 Components | Signals | OnPush |
Every extension you need
Batteries included: from basic formatting to advanced features.
57 total: 23 nodes, 9 marks, 25 extensions across 12 packages. All MIT licensed.
View All Packages →Built for production
Architecture decisions that make the difference at scale.
Schema Conflict Detection
Duplicate extension names throw a clear error at startup. No mysterious production bugs from silent overwrites.
Extension Composability
create() → configure() → extend() with this.parent?.() to call the base version. Override any hook while preserving parent behavior. Fully typed.
Fluent Command API
editor.chain().focus().toggleBold().run() chains commands on a shared transaction. editor.can().toggleBold() dry-runs without side effects. Fully typed.
XSS-Hardened Images
Blocks javascript:, vbscript:, file: protocols across four layers: parseHTML, renderHTML, commands, and input rules.
Global Attribute Injection
addGlobalAttributes() lets extensions inject attributes into node types they don't own. TextAlign, TextColor, FontSize, Highlight, and UniqueID all use this pattern. Zero coupling.
Zero-Jitter Floating UI
All floating elements use position: absolute inside the editor with @floating-ui/dom. CSS compositor handles scroll. Zero JS during scroll events.
SSR Ready
Server-side rendering via linkedom. Generate HTML on the server without a browser. Works with Angular Universal, Astro, and any Node.js environment.
Framework-agnostic core, Angular first
The core works with any framework. Angular, React, and Vue components ship today.
Simple, transparent pricing
Open source core, MIT licensed. Pro extensions coming soon for teams that need more.
- Complete editor engine
- Angular components (editor, toolbar, menus)
- Full tables: merge, resize, styling
- 57 extensions included
- Built-in toolbar & theme (light + dark)
- Image upload, emoji picker & mentions
- React & Vue components also available
Everything in Open Source, plus:
- Real-time collaboration (Yjs/CRDT)
- Inline comments & threads
- Track changes & revision history
- PDF / Word / Markdown export
- AI writing assistant
- Priority support & SLA
- ··· And more planned