npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@richscripts/richtexteditor

v2.4.0

Published

A full-featured JavaScript rich text editor (WYSIWYG) with toolbar, plugins, i18n support, a built-in AI Toolkit (Ask AI, AI Chat, AI Review drawer, BYOK resolver), structured content APIs (JSON/Markdown), and an optional collaboration / review stack: sla

Readme

Rich Text Editor

Rich Text Editor is a browser-based WYSIWYG editor with toolbar customization, plugins, localization, image editing, PDF export, and classic HTML APIs.

What's in v2.2

A full collaborative-document workspace, not just a textarea replacement:

  • AI Toolkit — in-editor proofread / rewrite / summarize / translate / chat, with streaming responses, an inline preview drawer, and a persistent accept/reject review ledger. Bring your own provider (OpenAI / Anthropic / Azure OpenAI / Groq / Ollama / custom) via editor.aiToolkit.setResolver() or the server-side IRichTextBoxAiResolver interface.
  • Per-node Yjs CRDT engine (new in 2.2)editor.collab.attach({ doc, provider, textSync: "crdt" }) activates character-level concurrent typing on the same paragraph with deterministic merge resolution, presence cursors via Y.RelativePosition-encoded awareness, and per-author Y.UndoManager (Ctrl-Z undoes only your edits). Pairs with any Yjs provider you self-host. Ships in the base license.
  • Slash commands & mentions/ at the start of a line opens a command palette; @ and # open mention pickers via editor.slashCommands.register() and editor.mentions.register().
  • Comments & tracked changes — threaded inline comments on text selections and block/media content such as images or tables (editor.comments.add/reply/resolve), tracked-changes mode, per-author colors and labels.
  • Comments-only review mode — set commentsOnly: true or call editor.setCommentsOnly(true) to lock document edits while still allowing inline comments and review discussion.
  • Restricted editing templates — set restrictedEditingMode: true to lock the document except for spans tagged data-rte-editable="true". Mark fillable regions at runtime with editor.restrictedEditing.markSelection(); toggle the lock via editor.restrictedEditing.enable() / disable() / goToNext(). Use it for forms, contracts, fillable templates — only the marked regions accept input.
  • Revision history — named snapshots, diff view, restore (editor.revisionHistory.snapshot/diff/restore).
  • Dictation — Web Speech API integration (editor.dictation.toggle()) with multi-language support.
  • DOCX import + export — import Word documents through editor.aiToolkit.importDocx({ file?, mode? }) and generate deterministic HTML → .docx via editor.aiToolkit.exportDocx({ filename }); preserves headings, lists, tables, images.
  • Structured content bridgeeditor.getJSON() / setJSON(), fromMarkdown() / toMarkdown(), renderHTML(), validateStructuredContent() — for SSR, JSON storage, and Markdown round-trip. The packaged schema now preserves merge fields, ordered-list marker styles (A / a / I / i), table-of-contents blocks, footnotes, and editor page breaks instead of collapsing them into opaque HTML.
  • Accessibility audit helperRichTextEditor.auditAccessibility() / auditAccessibility() catches empty headings, skipped heading levels, missing image alt text, and tables without header cells in browser or Node workflows.
  • In-editor accessibility repair panel — the packaged accessibilitychecker plugin adds a side panel (editor.accessibilityChecker.open/close/toggle/run/repair) with focused fixes for missing image alt text, empty headings, skipped heading levels, and headerless tables. Use accessibilityCheckerAutoOpen to keep the workflow visible during review passes.
  • Restricted editing templates — the packaged restrictedediting plugin lets apps lock the document root while keeping marked islands editable (editor.restrictedEditing.enable/disable/toggle/list/goToNext/goToPrevious). Mark reusable fields with data-rte-editable in template HTML or call editor.restrictedEditing.markSelection({ label }) while authoring.
  • Document outline + TOC helpersRichTextEditor.getDocumentOutline() / getDocumentOutline() extracts a flat heading outline (id, text, level, path), while getTableOfContents() returns a nested tree and syncTableOfContents() repopulates packaged TOC blocks from live headings. The same TOC helpers can also persist TinyMCE-style display settings such as ordered, orderedListType, and includeTitle for numbered or titleless navigation blocks. TOC items can also expose optional itemIndex / indexLabel metadata via indexMode: "linear" | "hierarchical" so custom sidebars can mirror Tiptap-style numbered navigation without reparsing headings twice.
  • Footnote extraction helperRichTextEditor.getFootnotes() / getFootnotes() returns sorted { id, number, refId, text, path } metadata from HTML or structured JSON so review sidebars and DOCX import screens can inspect Word-style citations without reparsing the document.
  • Live document outline panel — the packaged documentoutline plugin adds a toggleable browser-side heading sidebar (editor.documentOutline.open/close/toggle/list/refresh) so long documents get CKEditor-style section navigation without custom app code. Use documentOutlineAutoOpen, documentOutlineMinLevel, and documentOutlineMaxLevel to tune the panel.
  • Packaged content minimap — the packaged contentminimap plugin adds a TinyMCE/CKEditor-style miniature document preview (editor.contentMinimap.open/close/toggle/refresh/isOpen) with click-and-drag viewport navigation for long documents. Use contentMinimapAutoOpen, contentMinimapWidth, and contentMinimapScale to tune the panel.
  • Checklist / task-list Markdown- [x] done and - [ ] todo round-trip through fromMarkdown() / toMarkdown() and render as disabled checkbox lists in HTML / SSR output.
  • Markdown shortcut helper paritygetMarkdownShortcutAction() now recognizes headings, quotes, ordered/bullet/task lists, horizontal rules (---) and fenced code blocks (````` / ~~~lang) so custom wrappers can mirror the same typing affordances exposed by current editor competitors.
  • Word + character statisticseditor.getTextStatistics() / getSelectionStatistics() expose document + selection counts, and the built-in bottom bar can show characters, words, or both.
  • Case change commands — built-in ucase, lcase, and titlecase commands let toolbars or custom integrations quickly apply Upper Case, Lower Case, or Title Case transforms without leaving the editor.
  • Document metrics helperRichTextEditor.getDocumentMetrics() / getDocumentMetrics() adds paragraph, sentence, heading, image, table, link, and estimated reading-time counts for analytics and publishing workflows.
  • Document page setup metadataRichTextEditor.getDocumentPageSetup() / setDocumentPageSetup() lets apps persist page format, margins, orientation, and export header/footer HTML in the structured-content document for print/PDF workflows.
  • Framework wrappers — React (@richscripts/richtexteditor/react), Vue (@richscripts/richtexteditor/vue), Angular (@richscripts/richtexteditor/angular), Blazor wrapper, ASP.NET Core tag helper (<richtextbox> from the sister NuGet package). Framework refs/components also expose the document-workflow helpers needed for outline, TOC, page-setup, metrics, statistics, and accessibility flows without manually round-tripping through getJSON().
  • AI ghost-text autocomplete (2.3.0) — Copilot / Notion-AI-style inline completion: after a typing pause a greyed suggestion appears after the caret continuing your sentence; Tab accepts, Esc / typing dismisses. Bring-your-own resolver (config.ghostTextResolver({ before, after, full }) → string | Promise); inert until config.ghostText and a resolver are set, so no model ships and no network call happens on its own. Serialization-safe (the suggestion is a contenteditable=false span the caret stays before; getHTMLCode/getJSON strip it) and undo-friendly (accept via execCommand insertText). API: editor.requestGhostText() / acceptGhostText() / dismissGhostText() / hasGhostText() / setGhostTextResolver(); slash /ai complete.
  • Local draft autosave & crash recovery (2.3.0) — persists the document to localStorage as you type and offers to restore the unsaved draft on the next load (Gmail/Notion "never lose your work"). Opt-in via config.localDraft = true (or { key, intervalMs, ttlMs, promptRestore }). The draft is never auto-applied (server content shows until the user clicks Restore); stale drafts are pruned; saves on beforeunload. API: editor.saveLocalDraft() / hasLocalDraft() / getLocalDraft() / restoreLocalDraft() / clearLocalDraft().
  • Copy / Download as Markdown (2.3.0) — Notion-style export surfacing the core toMarkdown() engine: slash /copy as markdown + /download as markdown, or editor.getMarkdown() / editor.copyAsMarkdown() (clipboard, execCommand fallback) / editor.downloadMarkdown(name?) (saves a .md file, filename derived from the first heading). Read-only; disable with config.markdownExportEnabled = false.
  • Typewriter & focus writing modes (2.3.0) — two distraction-free modes. Typewriter mode pins the caret line to a fixed vertical anchor and scrolls the editable as you type (iA Writer / Typora / Ulysses style); focus mode dims every block except the one the caret is in (Notion / iA Writer style). Toggle independently via slash /typewriter + /focus mode or editor.toggleTypewriterMode() / editor.toggleFocusMode() (plus set…/is…). Both off by default (config.typewriterModeEnabled, config.focusModeEnabled, anchor via config.typewriterAnchor). Serialization-safe: purely presentational — focus state is runtime-only CSS classes, stripped around getHTMLCode/getJSON; typewriter mode only scrolls.
  • Foldable headings (2.3.0) — Obsidian/Notion/Word-style section folding: hover a heading and click the gutter chevron (or editor.toggleHeadingFold(h) / editor.foldAtCaret() / editor.unfoldAll(), slash /fold section) to collapse every block beneath it, up to the next heading of the same or higher level. Serialization-safe: fold state is runtime-only CSS classes (the chevron is a CSS ::before), and getHTMLCode/getJSON are wrapped to strip them — saved markup stays clean and folded content is never lost. Caret-safe. Disable with config.foldHeadingsEnabled = false.
  • Auto-embed media URLs on paste (2.3.0) — paste a bare YouTube or Vimeo URL on its own line and it becomes a responsive 16:9 embed (Notion/Medium style); also available as editor.embedUrl(url). Injection-safe by construction: the iframe src is rebuilt from a sanitized video id, never the raw input. Mid-paragraph and text-selected pastes stay links. Add providers via config.autoEmbedResolver(url); disable with config.autoEmbedEnabled = false.
  • Interactive to-do / task lists (2.3.0)editor.execCommand("inserttodolist") (slash /to-do, toolbar) inserts a checklist whose items each have a clickable checkbox; clicking toggles open/done (check + strike-through), Notion/GitHub style. The done state lives in data-checked and round-trips through getHTMLCode / getJSON; checkboxes are contenteditable="false" spans (no fragile <input>s) and re-bind on load via event delegation. Enter-created items are auto-normalized to stay well-formed.
  • Emoji :shortcode: autocomplete (2.3.0) — GitHub/Slack/Discord-style inline emoji entry: type a complete :shortcode: and it becomes the emoji (:fire: → 🔥, :+1: → 👍, :tada: → 🎉), or type : + a partial query for a keyboard-navigable popup (↑/↓, Enter/Tab, Esc). ~140 curated codes built in; extend or replace via config.emojiShortcodes. Word-boundary gated (so path:fire: is ignored) and inert inside code. Complements the emoji picker with fast keyboard-only entry. Disable with config.emojiAutocompleteEnabled = false.
  • Read-aloud / text-to-speech (2.3.0)editor.execCommand("readaloud") (slash /read aloud) opens a non-modal control bar (play/pause, stop, voice, rate) and reads the selection — or the whole document — aloud, highlighting each sentence as it is spoken (native selection, content untouched). Browser-native via the Web Speech API: no library bundled, no backend, no key. The speech-out complement to dictation; an accessibility win. API: editor.readAloud({rate,voice}) / editor.stopReadAloud(); tune with config.readAloudRate / config.readAloudHighlight.
  • Mermaid diagrams (2.3.0)editor.execCommand("insertdiagram") (slash /diagram) authors diagrams-as-code (flowchart, sequence, gantt, pie, class, state…) with a live preview and renders to SVG. No renderer bundled — uses config.diagramResolver (server-side render like Kroki), else a host-page window.mermaid, else a source <pre> fallback; the Mermaid source round-trips in data-diagram and re-renders via editor.renderDiagrams(). Double-click to edit; injection-safe contenteditable blocks. Pairs with the equation editor's same host-supplies-the-renderer model.
  • Inline Markdown autoformat (2.3.0) — type the closing delimiter and the span converts in place: **bold**/__bold__bold, *italic*/_italic_italic, `code` → inline code, ~~strike~~ → strikethrough. Complements the existing block shortcuts (# , > , - , 1. , ---). Word-boundary gated so math (2*3), globs and snake_case are never reformatted; inert inside code/links; fully undoable. Disable with config.markdownInlineEnabled = false.
  • Email inline-style export (2.3.0)editor.getEmailHTML() returns email-client-safe HTML: curated computed styles written inline on every element (since Outlook/Gmail strip <style> and classes), class/id/contenteditable/data-rte-* removed, <script>/<style> dropped, content wrapped in a centered max-width table. { wrap:false } for a bare fragment, { width:N } for a custom width; tune the inlined set via config.emailInlineProperties. editor.execCommand("emailexport") (slash /email or toolbar) opens a copy-ready dialog.
  • Smart chips (2.3.0) — Google-Docs-style inline chips: editor.execCommand("insertdatechip") drops an interactive date pill (picker + machine-readable value); insertchip opens a Date/Person/Link menu. Person/Link chips use the optional config.chipResolver(query, type) for rich data, with a plain-input fallback. Atomic, injection-safe, round-trips through getHTMLCode.
  • Block drag-handles (2.3.0) — Notion-style ⋮⋮ handle on hover lets you drag-reorder top-level blocks. On by default; disable with config.blockDragHandles = false. The handle never enters the saved content.
  • Spell check (2.3.0)editor.execCommand("spellcheck"). Native browser spell-check by default (zero infra); wire config.spellCheckResolver(text) => Promise<[{word, suggestions}]> (LanguageTool / server / LLM) for a review panel with click-to-replace suggestions. Insert from the slash menu (/spellcheck) or toolbar.
  • Web-bookmark preview cards (2.3.0)editor.execCommand("insertbookmark") turns a URL into a rich link-preview card (favicon + title + description + domain). Works with zero backend (basic card from URL + favicon) or wire config.bookmarkResolver(url) => Promise<{title,description,image,favicon}> for full unfurled previews. Insert from the slash menu (/bookmark) or toolbar; http(s)-only with escaped metadata and rel="noopener".
  • Equation editor (2.3.0)editor.execCommand("insertmath") opens a TeX/LaTeX dialog with a live KaTeX/MathJax preview and edit-in-place support; emits stable .rte-math-inline markup that renders via whatever math renderer the host page loads. Insert from the slash menu (/equation) or toolbar.
  • Modern block types (2.3.0)callouts (info / success / warning / danger / note admonition boxes), multi-column layouts (2–4 responsive columns), and toggle / collapsible blocks (native <details>). Insert from the slash menu (/) or the toolbar; customize callout variants via config.calloutTypes. Editor-native (no server), round-trips through getHTMLCode / getJSON. Closes the Notion / Google Docs / CKEditor block-type gap.
  • Paste-pipeline hardening (2.2.4) — Word lists pre-converted before the attribute scrubber strips the metadata; TOC / PAGEREF / HYPERLINK / SEQ / STYLEREF / NOTEREF / REF / FORMTEXT / FORMCHECKBOX / DATE / TIME / FILENAME / AUTHOR / TITLE / SUBJECT / INDEX / MERGEFIELD field instructions stripped even when scrubbed-bare; instruction text split across continuation <span> runs caught with false-positive-safe guards; <style> / <script> / <head> / <meta> defense-in-depth; tool-specific class + data-* strip for Notion (notion-*, data-block-id), CKEditor (cke_*, data-cke-*), TinyMCE (mce_*, data-mce-*), Atlassian (confluence-*, data-confluence-*), and Google Docs (docs-internal-*, data-google-*); cleanup of empty <span></span> / <p></p> debris; smart-paste source toast detects Word / Google Docs / LibreOffice / Notion / Excel / Confluence. Opt-out via smartPasteToast: false.
  • Smart link paste (2.2.4) — pasting a URL or email while text is selected wraps the selection in <a href> instead of replacing it. Matches Google Docs / Notion / TipTap / ProseMirror behavior. Opt-out via smartLinkPaste: false.
  • Mobile toolbar mode, classic toolbar customization, plugins, localization, image editing, PDF export, paste-from-Word fidelity, find & replace, autosave, draft recovery.
  • Configurable empty-editor placeholders — set placeholder, placeholderShowOnlyWhenEditable, and placeholderColor to match the guided empty-state UX offered by current Tiptap and TinyMCE setups.
  • TypeScript declarations — 487-line index.d.ts with typed signatures for all 31 documented editor instance methods, the RichTextEditorCommand string-literal union (50+ built-in commands), event-handler signatures, and the RichTextEditorConfig interface.

The structured content bridge now returns a semantic document model while still carrying compatibility HTML and plain text:

{
  "type": "doc",
  "version": 2,
  "format": "richtexteditor-json",
  "html": "<p>Hello world</p>",
  "text": "Hello world",
  "content": [
    {
      "type": "paragraph",
      "content": [
        { "type": "text", "text": "Hello world" }
      ]
    }
  ]
}

Asset setup

Serve the richtexteditor/ folder from your app. The React and Vue wrappers default to loading assets from /richtexteditor.

Markdown, validation, and static rendering

import {
  auditAccessibility,
  createStructuredContent,
  fromMarkdown,
  getDocumentPageSetup,
  getDocumentMetrics,
  getDocumentOutline,
  getTableOfContents,
  getTextStatistics,
  renderHTML,
  repairAccessibilityIssue,
  setDocumentPageSetup,
  syncTableOfContents,
  toMarkdown,
  validateStructuredContent
} from "@richscripts/richtexteditor/integrations/shared";

const documentModel = fromMarkdown("## Hello\n\nThis now round-trips through **Markdown**.");
const html = renderHTML(documentModel);
const markdown = toMarkdown(documentModel);
const pagedDocument = setDocumentPageSetup(documentModel, {
  format: "Letter",
  margins: { top: "1in", right: "0.75in", bottom: "1in", left: "0.75in" }
});
const pageSetup = getDocumentPageSetup(pagedDocument);
const metrics = getDocumentMetrics(documentModel);
const outline = getDocumentOutline(documentModel);
const toc = getTableOfContents(documentModel, {
  minLevel: 2,
  maxLevel: 4,
  indexMode: "hierarchical"
});
const stats = getTextStatistics(documentModel);
const accessibility = auditAccessibility(documentModel);
const repairedDocument = repairAccessibilityIssue(documentModel, accessibility.issues[0], {
  altText: "Hero illustration"
});
const validation = validateStructuredContent(documentModel);
const syncedTocDocument = syncTableOfContents(documentModel, {
  ordered: true,
  orderedListType: "I",
  includeTitle: false
});

Structured content can also preserve document-automation nodes emitted by the editor UI:

const documentModel = createStructuredContent(
  '<p>Hello <span data-rte-merge-field="Customer.Name">Customer Name</span><sup data-rte-footnote-ref="1"><a href="#note-1">[1]</a></sup></p>' +
  '<div data-rte-footnotes="true"><div>Footnotes</div><ol><li id="note-1" data-rte-footnote-item="1">Imported from a template. <a href="#ref-1">↩</a></li></ol></div>'
);

console.log(documentModel.content[0].content[1].type); // "mergeField"
console.log(toMarkdown(documentModel)); // includes {{Customer.Name}} and [^1]

These helpers can now also run in Node for server-side rendering and content conversion without requiring a browser DOM.

const {
  auditAccessibility,
  createStructuredContent,
  getDocumentMetrics,
  getDocumentPageSetup,
  getDocumentOutline,
  getTableOfContents,
  getTextStatistics,
  renderHTML,
  repairAccessibilityIssue,
  setDocumentPageSetup,
  syncTableOfContents,
  toMarkdown,
  validateStructuredContent
} = require("@richscripts/richtexteditor/server");

const documentModel = createStructuredContent("<div data-rte-toc=\"true\"><div>Contents</div></div><h2>Hello</h2><p><strong>Server</strong> render</p>");
const html = renderHTML(documentModel);
const markdown = toMarkdown(documentModel);
const pagedDocument = setDocumentPageSetup(documentModel, {
  format: "A4",
  orientation: "portrait",
  margins: { top: "20mm", right: "16mm", bottom: "20mm", left: "16mm" }
});
const pageSetup = getDocumentPageSetup(pagedDocument);
const metrics = getDocumentMetrics(documentModel);
const outline = getDocumentOutline(documentModel);
const toc = getTableOfContents(documentModel, {
  minLevel: 2,
  maxLevel: 4,
  indexMode: "hierarchical"
});
const synced = syncTableOfContents(documentModel, {
  ordered: true,
  orderedListType: "A",
  includeTitle: false
});
const stats = getTextStatistics(documentModel);
const accessibility = auditAccessibility(documentModel);
const repairedDocument = repairAccessibilityIssue(documentModel, accessibility.issues[0], {
  altText: "Server-rendered architecture diagram"
});
const validation = validateStructuredContent(documentModel);

Use @richscripts/richtexteditor/server when you only need conversion and rendering on the server. Use @richscripts/richtexteditor/integrations/shared when you also need browser asset loading and editor bootstrapping helpers.

The same server/shared helpers also expose getTextStatistics(value) for consistent word and character counts outside the browser. The React, Vue, and Angular package entry points re-export this same helper family so framework apps can import editor components and document-workflow utilities from one place.

DOCX import

Current competitors like CKEditor, TinyMCE, and Tiptap all market Word/DOCX import alongside export. Rich Text Editor now ships a matching browser helper for the client side of that flow:

await editor.aiToolkit.importDocx({
  url: "/richtextbox/import/docx",
  mode: "replace"
});

Pass file to skip the built-in file picker, or use mode: "insert" to insert the converted HTML at the current caret instead of replacing the whole document. The helper expects the server endpoint to return either raw HTML or JSON with an html field.

React

import { useState } from "react";
import { RichTextEditorReact } from "@richscripts/richtexteditor/react";

export default function EditorPage() {
  const [html, setHtml] = useState("<p>Hello world</p>");

  return (
    <RichTextEditorReact
      value={html}
      onChange={setHtml}
      assetBasePath="/richtexteditor"
      style={{ minHeight: 360 }}
    />
  );
}

Vue

import { createApp, ref } from "vue";
import { RichTextEditorVue } from "@richscripts/richtexteditor/vue";

const app = createApp({
  components: { RichTextEditorVue },
  setup() {
    const documentModel = ref({
      type: "doc",
      version: 2,
      format: "richtexteditor-json",
      content: [
        {
          type: "paragraph",
          content: [{ type: "text", text: "Hello world" }]
        }
      ]
    });

    return { documentModel };
  }
});
<RichTextEditorVue
  v-model="documentModel"
  value-format="json"
  asset-base-path="/richtexteditor"
  style="min-height: 360px"
/>

Angular

Angular apps can now use the packaged standalone wrapper component:

import { Component } from "@angular/core";
import { RichTextEditorAngularComponent } from "@richscripts/richtexteditor/angular";

@Component({
  selector: "app-root",
  standalone: true,
  imports: [RichTextEditorAngularComponent],
  template: `
    <rich-text-editor
      [assetBasePath]="'/assets/richtexteditor'"
      [value]="documentModel"
      [valueFormat]="'json'"
      (change)="handleChange($event.value)"
    />
  `
})
export class AppComponent {
  documentModel = {
    type: "doc",
    version: 2,
    format: "richtexteditor-json",
    content: [
      {
        type: "paragraph",
        content: [{ type: "text", text: "Hello from Angular" }]
      }
    ]
  };

  handleChange(value: unknown) {
    this.documentModel = value as typeof this.documentModel;
  }
}

The Angular wrapper exposes the same JSON bridge and convenience instance methods as the React and Vue wrappers: focus(), getEditor(), getHTMLCode(), getJSON(), setHTMLCode(), setJSON(), and plugin accessors such as getAiToolkit() / getCollab() / getComments().

The repo also includes a full Angular starter in Demos/rte-ng-ts/ that uses the same wrapper pattern.

Classic usage

<link rel="stylesheet" href="/richtexteditor/rte_theme_default.css" />
<script src="/richtexteditor/rte.js"></script>
<script src="/richtexteditor/plugins/all_plugins.js"></script>
<!-- Production: swap the line above for the minified bundle (~56% smaller, identical behaviour):
     <script src="/richtexteditor/plugins/all_plugins.min.js"></script> -->

<div id="editor"></div>
<script>
  var editor = new RichTextEditor("#editor", {
    placeholder: "Write something...",
    placeholderShowOnlyWhenEditable: true,
    commentsOnly: false,
    restrictedEditingMode: false,
    accessibilityCheckerAutoOpen: false,
    documentOutlineAutoOpen: false,
    documentOutlineMinLevel: 1,
    documentOutlineMaxLevel: 3
  });
  editor.setHTMLCode("<p>Hello world</p>");
  console.log(editor.getJSON());
</script>

Restricted editing is meant for contract, intake, and mail-merge style templates:

<p>Hello <span data-rte-editable="true" data-rte-editable-label="Customer Name">Customer Name</span>,</p>
<p>Your case number is <span data-rte-editable="true" data-rte-editable-label="Case ID">0000</span>.</p>
editor.setHTMLCode(templateHtml);
editor.restrictedEditing.enable();
editor.restrictedEditing.goToNext();

Template authors can also mark regions interactively before switching modes:

editor.restrictedEditing.markSelection({ label: "Account manager" });
editor.restrictedEditing.markSelection({ block: true, label: "Custom notes" });
editor.restrictedEditing.enable();

In order to start using Rich Text Editor, configure or customize it further, please visit the documentation.

License

For licensing information please read Licensing Info.