// Type definitions for richtexteditor 2.x // Project: https://richtexteditor.com // // These declarations cover the public surface documented at // https://richtexteditor.com/docs and exercised by the React / Vue // wrappers in this package. The editor itself is shipped as a single // bundle (`richtexteditor/rte.js`) that attaches `RichTextEditor` to // the global scope; the typings below describe both the constructor // and the per-instance methods. // ===================== // Structured content (JSON / Markdown) // ===================== export type RichTextEditorValueFormat = "html" | "json"; export interface RichTextEditorStructuredMark { type: string; attrs?: Record; } export interface RichTextEditorPageMargins { top?: string; right?: string; bottom?: string; left?: string; } export interface RichTextEditorPageSetup { format?: string; orientation?: "portrait" | "landscape"; width?: string; height?: string; margins?: RichTextEditorPageMargins; headerHtml?: string; footerHtml?: string; } export interface RichTextEditorStructuredDocumentAttributes { pageSetup?: RichTextEditorPageSetup; [key: string]: unknown; } export interface RichTextEditorStructuredDocument { type: "doc"; version: number; format: string; attrs?: RichTextEditorStructuredDocumentAttributes; html?: string; text?: string; content?: RichTextEditorStructuredNode[]; } export interface RichTextEditorStructuredNode { type: string; attrs?: Record; content?: RichTextEditorStructuredNode[]; html?: string; marks?: RichTextEditorStructuredMark[]; text?: string; [key: string]: unknown; } export interface RichTextEditorStructuredContentLike { html?: string; content?: RichTextEditorStructuredNode | RichTextEditorStructuredNode[]; [key: string]: unknown; } export interface RichTextEditorValidationIssue { message: string; path: string; } export interface RichTextEditorValidationResult { document: RichTextEditorStructuredDocument; issues: RichTextEditorValidationIssue[]; valid: boolean; } export type RichTextEditorAccessibilitySeverity = "error" | "warning"; export interface RichTextEditorAccessibilityIssue { code: string; message: string; path: string; severity: RichTextEditorAccessibilitySeverity; } export interface RichTextEditorAccessibilityRepairOptions { altText?: string; headingText?: string; targetLevel?: number; } export interface RichTextEditorAccessibilityResult { document: RichTextEditorStructuredDocument; issues: RichTextEditorAccessibilityIssue[]; valid: boolean; } export type RichTextEditorLinkAuditSeverity = "error" | "warning"; export interface RichTextEditorLinkAuditIssue { code: string; href?: string; message: string; path: string; severity: RichTextEditorLinkAuditSeverity; } export interface RichTextEditorLinkAuditOptions { allowedDomains?: string[]; allowedProtocols?: string[]; flagNewWindowWithoutRel?: boolean; requireHttps?: boolean; } export interface RichTextEditorLinkAuditResult { document: RichTextEditorStructuredDocument; issues: RichTextEditorLinkAuditIssue[]; valid: boolean; } export interface RichTextEditorTextStatistics { characters: number; charactersNoSpaces: number; words: number; selectedCharacters: number; selectedCharactersNoSpaces: number; selectedWords: number; } export interface RichTextEditorDocumentMetrics extends RichTextEditorTextStatistics { paragraphs: number; sentences: number; headings: number; images: number; tables: number; links: number; estimatedReadingMinutes: number; } export interface RichTextEditorDocumentOutlineItem { id: string; level: number; path: string; text: string; } export interface RichTextEditorTableOfContentsItem extends RichTextEditorDocumentOutlineItem { itemIndex?: number; indexLabel?: string; children: RichTextEditorTableOfContentsItem[]; } export interface RichTextEditorFootnoteItem { id: string; number: number; path: string; refId: string; text: string; } export interface RichTextEditorTableOfContentsOptions { minLevel?: number; maxLevel?: number; indexMode?: "none" | "linear" | "hierarchical"; title?: string; includeTitle?: boolean; ordered?: boolean; orderedListType?: "1" | "A" | "a" | "I" | "i"; } export type RichTextEditorStructuredInput = | string | RichTextEditorStructuredDocument | RichTextEditorStructuredContentLike; // ===================== // Commands // ===================== /** * Built-in command identifiers accepted by execCommand / isCommandEnabled / * isCommandActive. The list is intentionally non-exhaustive — custom commands * registered via createToolbarButton are also valid execCommand inputs, hence * the `string` fallback. */ export type RichTextEditorCommand = | "bold" | "italic" | "underline" | "strikethrough" | "subscript" | "superscript" | "fontname" | "fontsize" | "forecolor" | "backcolor" | "removeformat" | "justifyleft" | "justifycenter" | "justifyright" | "justifyfull" | "indent" | "outdent" | "insertorderedlist" | "insertunorderedlist" | "insertimage" | "insertlink" | "unlink" | "inserthorizontalrule" | "insertpagebreak" | "inserttable" | "insertrowbefore" | "insertrowafter" | "insertcolumnbefore" | "insertcolumnafter" | "deleterow" | "deletecolumn" | "deletetable" | "undo" | "redo" | "selectall" | "copy" | "cut" | "paste" | "ucase" | "lcase" | "titlecase" | "source" | "fullscreen" | "preview" | "print" | "pastetext" | "pastefromword" | "paragraph" | "heading" | "documentoutline" | "contentminimap" | "accessibilitychecker" | "ai-ask" | "ai-chat" | "ai-review" | "ai-export-docx" | "ai-import-docx" | "dictation-toggle" // Modern block types (2.3.0) — backed by the blocktypes plugin. | "insertcallout" | "insertcolumns" | "inserttoggle" // Interactive to-do / task list (2.3.0) — backed by the todolist plugin. | "inserttodolist" // Equation editor (2.3.0) — backed by the mathdialog plugin. | "insertmath" // Mermaid diagram (2.3.0) — backed by the mermaiddiagram plugin. | "insertdiagram" // Bookmark preview card (2.3.0) — backed by the bookmarkcard plugin. | "insertbookmark" // Spell check (2.3.0) — backed by the spellcheck plugin. | "spellcheck" // Smart chips (2.3.0) — backed by the smartchips plugin. | "insertdatechip" | "insertchip" // Email toolkit (2.3.0) — backed by the emailtoolkit plugin. | "emailexport" // Read-aloud / text-to-speech (2.3.0) — backed by the readaloud plugin. | "readaloud" | string; // ===================== // Selection // ===================== export interface RichTextEditorSelection { /** The native Range, when one is available. */ range?: Range; /** The selected control element (image / table / hr) or null for caret/text selections. */ control?: Element | null; /** Whether the selection is collapsed (no range / caret only). */ isCollapsed: boolean; /** Whether the selection covers the entire document. */ isAll?: boolean; [key: string]: unknown; } // ===================== // AI Toolkit (v2.0) // ===================== export type RichTextEditorAiOperationType = | "preview-suggestion" | "replace-document" | "insert-below" | "add-comment" | string; export interface RichTextEditorAiOperation { type: RichTextEditorAiOperationType; text: string; reason?: string; [key: string]: unknown; } export interface RichTextEditorAiResponse { sourceLabel?: string; reason?: string; message?: string; result?: string; operations?: RichTextEditorAiOperation[]; [key: string]: unknown; } export interface RichTextEditorAiRequest { mode: string; prompt?: string; source?: string; selectionText?: string; documentText?: string; hasSelection?: boolean; language?: string; [key: string]: unknown; } export interface RichTextEditorAiStreamHandle { abort(): void; promise?: Promise; } export interface RichTextEditorAiStreamRequestOptions { url: string; body: Record; headers?: Record; onDelta?(delta: string, accumulated: string): void; onResponse?(response: RichTextEditorAiResponse): void; onDone?(text: string): void; onError?(error: Error): void; } export interface RichTextEditorAiExportDocxOptions { filename?: string; fileName?: string; title?: string; url?: string; download?: boolean; } export interface RichTextEditorAiImportDocxOptions { file?: Blob | File | null; filename?: string; fileName?: string; url?: string; apply?: boolean; mode?: "replace" | "insert"; onError?(error: Error): void; } export interface RichTextEditorAiToolkit { setResolver( resolver: (request: RichTextEditorAiRequest) => Promise | RichTextEditorAiResponse, ): void; openDialog(options?: { presetMode?: string; prompt?: string }): void; openChatPanel(options?: { focusComposer?: boolean }): void; openReviewPanel(): void; runQuickAction(mode: string, options?: Record): Promise; streamRequest(options: RichTextEditorAiStreamRequestOptions): RichTextEditorAiStreamHandle; exportDocx(options?: RichTextEditorAiExportDocxOptions): Promise; importDocx(options?: RichTextEditorAiImportDocxOptions): Promise; refreshRemoteReviewState?(force?: boolean): Promise; acceptInline?(text: string): void; rejectInline?(): void; } // ===================== // Dictation // ===================== export interface RichTextEditorDictation { isSupported(): boolean; isListening(): boolean; start(options?: { language?: string; continuous?: boolean }): void; stop(): void; toggle(options?: { language?: string }): void; } // ===================== // Revision history // ===================== export interface RichTextEditorRevisionEntry { id: string; name?: string; createdAt: number; html: string; authorId?: string; authorName?: string; } export interface RichTextEditorRevisionDiff { oldHtml: string; newHtml: string; unifiedDiff?: string; } export interface RichTextEditorRevisionHistory { snapshot(name?: string): RichTextEditorRevisionEntry; promptAndSnapshot(): Promise; rename(id: string, name: string): void; list(): RichTextEditorRevisionEntry[]; listNamed(): RichTextEditorRevisionEntry[]; diff(idA: string, idB: string): RichTextEditorRevisionDiff; restore(id: string): void; remove(id: string): void; } // ===================== // Yjs collab // ===================== export interface RichTextEditorCollabAttachOptions { doc: unknown; provider: unknown; textSync?: boolean; awareness?: unknown; fragmentName?: string; /** * The Yjs module (the `* as Y` namespace). REQUIRED to be the SAME Yjs * instance that created `doc` and backs `provider` whenever the editor can't * find it on `window.Y`. The CRDT engine builds document nodes with this * module; mixing two Yjs copies throws "Unexpected content type in insert * operation" and silently breaks text sync (yjs issue #438). */ Y?: unknown; /** * When attaching to an EMPTY shared document, seed it from the editor's * current content (first-writer) instead of clearing the editor. Default * `true`. Set `false` to always let the shared document win (the editor is * cleared if the shared doc is empty). Reconciliation waits for the * provider's initial sync so it never clobbers not-yet-synced remote state. */ seedFromHost?: boolean; } export interface RichTextEditorCollab { attach(options: RichTextEditorCollabAttachOptions): void; detach(): void; } // ===================== // Slash commands / mentions / comments / review ledger // ===================== export interface RichTextEditorSlashCommand { id: string; label: string; description?: string; icon?: string; group?: string; run(editor: RichTextEditorInstance, context?: unknown): void; } export interface RichTextEditorSlashCommands { register(command: RichTextEditorSlashCommand): void; remove(id: string): void; list(): RichTextEditorSlashCommand[]; } export interface RichTextEditorMentionItem { id: string; name: string; meta?: unknown; } export interface RichTextEditorMentionProvider { trigger: string; search(query: string): | Promise | RichTextEditorMentionItem[]; render?(item: RichTextEditorMentionItem): string; } export interface RichTextEditorMentions { register(provider: RichTextEditorMentionProvider): void; remove(trigger: string): void; } export interface RichTextEditorCommentEntry { id: string; authorId?: string; authorName?: string; text: string; createdAt: number; resolved?: boolean; parentId?: string; } export interface RichTextEditorComments { add(text: string, options?: { authorName?: string }): RichTextEditorCommentEntry; reply(parentId: string, text: string, options?: { authorName?: string }): RichTextEditorCommentEntry; resolve(id: string): void; delete(id: string): void; list(): RichTextEditorCommentEntry[]; } export interface RichTextEditorRestrictedEditingMarkOptions { /** Optional aria-label to apply to the new wrapper span. */ label?: string; } export interface RichTextEditorRestrictedEditing { isEnabled(): boolean; enable(): boolean; disable(): boolean; toggle(): boolean; /** Wrap the current selection in a `` so it remains editable when restricted mode is on. */ markSelection(options?: RichTextEditorRestrictedEditingMarkOptions): Element | null; /** Remove the editable wrapper around the given node (or the current selection's wrapper). */ unmark(node?: Element): boolean; list(): Element[]; /** Move caret to the next editable region (wraps around). */ goToNext(): Element | null; /** Move caret to the previous editable region. */ goToPrev(): Element | null; } export interface RichTextEditorDocumentOutlinePanelItem { id: string; level: number; text: string; element: Element; } export interface RichTextEditorDocumentOutlinePanel { close(): void; list(): RichTextEditorDocumentOutlinePanelItem[]; open(): void; refresh(): void; toggle(): void; } export interface RichTextEditorContentMinimap { close(): void; isOpen(): boolean; open(): void; refresh(): void; toggle(): void; } export interface RichTextEditorAccessibilityChecker { close(): void; getIssues(): RichTextEditorAccessibilityIssue[]; open(): void; refresh(): RichTextEditorAccessibilityResult; repair(issueIndex: number, options?: RichTextEditorAccessibilityRepairOptions): RichTextEditorAccessibilityResult; run(): RichTextEditorAccessibilityResult; toggle(): void; } export interface RichTextEditorRestrictedEditingRegion { id: string; label?: string; element: Element; } export interface RichTextEditorRestrictedEditingMarkOptions { block?: boolean; id?: string; label?: string; placeholder?: string; } export interface RichTextEditorRestrictedEditing { clearSelectionRegion(): boolean; disable(): void; enable(): void; goToNext(): Element | null; goToPrevious(): Element | null; isEnabled(): boolean; list(): RichTextEditorRestrictedEditingRegion[]; markSelection(options?: RichTextEditorRestrictedEditingMarkOptions): Element | null; refresh(): void; toggle(): boolean; } export type RichTextEditorReviewState = "pending" | "accepted" | "rejected" | string; export interface RichTextEditorReviewLedgerEntry { id: string; state: RichTextEditorReviewState; text: string; reason?: string; createdAt: number; metadata?: Record; } export interface RichTextEditorReviewLedger { add(entry: Omit & { id?: string }): RichTextEditorReviewLedgerEntry; update(id: string, patch: Partial): RichTextEditorReviewLedgerEntry | undefined; remove(id: string): void; list(state?: RichTextEditorReviewState): RichTextEditorReviewLedgerEntry[]; get(id: string): RichTextEditorReviewLedgerEntry | undefined; } // ===================== // Toolbar / dialog factories // ===================== export interface RichTextEditorToolbarButtonOptions { text?: string; hint?: string; iconUrl?: string; shortcut?: string; click?(editor: RichTextEditorInstance): void; command?: string; } export interface RichTextEditorToolbarDropDownItem { text: string; value?: string | number; hint?: string; className?: string; } export interface RichTextEditorToolbarDropDownOptions { width?: string | number; items: RichTextEditorToolbarDropDownItem[]; onSelect?(value: string | number, item: RichTextEditorToolbarDropDownItem): void; } export interface RichTextEditorDialogOptions { title?: string; width?: string | number; height?: string | number; /** Inner HTML for the dialog body (alternative to `html`). */ body?: string; html?: string; /** Buttons rendered in the dialog footer. Defaults to OK / Cancel when omitted. */ buttons?: Array<{ text: string; isDefault?: boolean; isCancel?: boolean; click?(): void; }>; onClose?(): void; } // ===================== // Events // ===================== /** * Built-in editor events. Custom events fired by plugins are also valid * (matched by the `string` fallback). * * - `change` — fired after editable content changes (content edits, paste, * undo/redo, AI replacement). Handler signature: `() => void`. * - `selectionchange` — fired after the selection moves (caret move, range * change, control selection). Handler signature: `() => void`. * - `exec_command` — fired when a toolbar / shortcut command runs. Handler * signature: `(commandName: string, value?: unknown) => void`. * - `change_html_view` — fired when the editor toggles between Design and * HTML/source modes. Handler signature: `(isHtmlView: boolean) => void`. * - `keydown` / `keyup` / `keypress` — pass-through of editable keyboard * events. Handler signature: `(event: KeyboardEvent) => void`. * - `focus` / `blur` — editable focus / blur. Handler signature: * `(event: FocusEvent) => void`. */ export type RichTextEditorEventName = | "change" | "selectionchange" | "exec_command" | "change_html_view" | "keydown" | "keyup" | "keypress" | "focus" | "blur" // Reserved for the AI toolkit — not yet emitted by the current build. | "ai_request" | "ai_response" | "ai_review_added" | "ai_review_resolved" | "comment_added" | "comment_resolved" | "revision_snapshot" | "charlimit" | "commentsonlychanged" | "contentchange" | "resize" | "customdialog" | string; export type RichTextEditorEventHandler = (...args: any[]) => void; // ===================== // Editor instance // ===================== export interface RichTextEditorReadabilityStats { words: number; sentences: number; syllables: number; characters: number; avgWordsPerSentence: number; avgSyllablesPerWord: number; /** Flesch Reading Ease (higher = easier; ~0–100 typical). */ fleschReadingEase: number; /** Flesch–Kincaid US grade level (clamped at 0). */ fleschKincaidGrade: number; readingTimeMinutes: number; /** Human-readable reading time, e.g. "3 min" or "20 sec". */ readingTimeText: string; /** Plain-language interpretation of the reading-ease score. */ easeLabel: string; } export interface RichTextEditorImportOptions { /** `replace` (default) swaps the whole document; `insert` adds at the caret. */ mode?: "replace" | "insert"; /** `accept` attribute for the file picker (default `.md,.markdown,.html,.htm,.txt,.doc,.docx`). */ accept?: string; } export interface RichTextEditorWordExportOptions { /** Document title (defaults to the first heading). */ title?: string; /** Body font-family (default `"Calibri, 'Segoe UI', Arial, sans-serif"`). */ fontFamily?: string; /** Body font-size (default `"11pt"`). */ fontSize?: string; /** `@page` size (default `"8.5in 11in"`). */ pageSize?: string; /** `@page` margin (default `"1in"`). */ margin?: string; /** Landscape orientation (default `false`). */ landscape?: boolean; } export interface RichTextEditorInstance { // ---- Lifecycle / events ---- /** Subscribe to an editor event. See {@link RichTextEditorEventName}. */ attachEvent(name: RichTextEditorEventName, handler: RichTextEditorEventHandler): void; /** Unsubscribe from an editor event. */ detachEvent(name: RichTextEditorEventName, handler: RichTextEditorEventHandler): void; /** Move keyboard focus into the editable area. */ focus(): void; // ---- Content I/O ---- /** Returns the current HTML string. */ getHTMLCode(): string; /** Replaces editable content with the provided HTML and resets undo stack. */ setHTMLCode(html: string): unknown; /** Returns the document as plain text (no markup). */ getPlainText(): string; // The structured-content instance methods below are installed by the // structured-content bridge. The React/Vue/Angular wrappers install it // automatically; in any other setup call // `require("@richscripts/richtexteditor/integrations/shared").installStructuredContentBridge()` // once before relying on them. They are typed optional because a plain // `