roosterjs
Version:
A simple facade for all roosterjs code
5,321 lines • 188 kB
TypeScript
// Type definitions for roosterjs (Version 7.13.0)
// Generated by dts tool from roosterjs
// Project: https://github.com/Microsoft/roosterjs
/**
* Create an editor instance with most common options
* @param contentDiv The html div element needed for creating the editor
* @param additionalPlugins The additional user defined plugins. Currently the default plugins that are already included are
* DefalutShortcut, HyperLink, Paste, and ContentEdit, user don't need to add those.
* @param initialContent The initial content to show in editor. It can't be removed by undo, user need to manually remove it if needed.
* @returns The editor instance
*/
export function createEditor(contentDiv: HTMLDivElement, additionalPlugins?: EditorPlugin[], initialContent?: string): Editor;
/**
* Information of current OS and web browser
*/
export interface BrowserInfo {
/**
* Wether current OS is Mac
*/
readonly isMac?: boolean;
/**
* Whether current OS is Windows
*/
readonly isWin?: boolean;
/**
* Whether current browser is using webkit kernal
*/
readonly isWebKit?: boolean;
/**
* Whether current browser is Internet Explorer
*/
readonly isIE?: boolean;
/**
* Whether current browser is IE10 or IE11
*/
readonly isIE11OrGreater?: boolean;
/**
* Whether current browser is Safari
*/
readonly isSafari?: boolean;
/**
* Whether current browser is Chrome
*/
readonly isChrome?: boolean;
/**
* Whether current browser is Firfox
*/
readonly isFirefox?: boolean;
/**
* Whether current browser is Edge
*/
readonly isEdge?: boolean;
/**
* Whether current browser is IE/Edge
*/
readonly isIEOrEdge?: boolean;
}
/**
* Command strings for Document.execCommand() API
* https: */
export const enum DocumentCommand {
/**
* Changes the browser auto-link behavior (Internet Explorer only)
*/
AutoUrlDetect = "AutoUrlDetect",
/**
* Changes the document background color. In styleWithCss mode, it affects the background color of the containing block instead.
* This requires a <color> value string to be passed in as a value argument. Note that Internet Explorer uses this to set the
* text background color.
*/
BackColor = "backColor",
/**
* Toggles bold on/off for the selection or at the insertion point. Internet Explorer uses the <strong> tag instead of <b>.
*/
Bold = "bold",
/**
* Clears all authentication credentials from the cache.
*/
ClearAuthenticationCache = "ClearAuthenticationCache",
/**
* Makes the content document either read-only or editable. This requires a boolean true/false as the value argument.
* (Not supported by Internet Explorer.)
*/
ContentReadOnly = "contentReadOnly",
/**
* Copies the current selection to the clipboard. Conditions of having this behavior enabled vary from one browser to another,
* and have evolved over time. Check the compatibility table to determine if you can use it in your case.
*/
Copy = "copy",
/**
* Creates an hyperlink from the selection, but only if there is a selection. Requires a URI string as a value argument for the
* hyperlink's href. The URI must contain at least a single character, which may be whitespace.
* (Internet Explorer will create a link with a null value.)
*/
CreateLink = "createLink",
/**
* Removes the current selection and copies it to the clipboard. When this behavior is enabled varies between browsers,
* and its conditions have evolved over time. Check the compatibility table for usage details.
*/
Cut = "cut",
/**
* Adds a <small> tag around the selection or at the insertion point. (Not supported by Internet Explorer.)
*/
DecreaseFontSize = "decreaseFontSize",
/**
* Changes the paragraph separator used when new paragraphs are created in editable text regions. See Differences in markup
* generation for more details.
*/
DefaultParagraphSeparator = "defaultParagraphSeparator",
/**
* Deletes the current selection.
*/
Delete = "delete",
/**
* Enables or disables the table row/column insertion and deletion controls. (Not supported by Internet Explorer.)
*/
EnableInlineTableEditing = "enableInlineTableEditing",
/**
* Enables or disables the resize handles on images and other resizable objects. (Not supported by Internet Explorer.)
*/
EnableObjectResizing = "enableObjectResizing",
/**
* Changes the font name for the selection or at the insertion point. This requires a font name string (like "Arial")
* as a value argument.
*/
FontName = "fontName",
/**
* Changes the font size for the selection or at the insertion point. This requires an integer from 1-7 as a value argument.
*/
FontSize = "fontSize",
/**
* Changes a font color for the selection or at the insertion point. This requires a hexidecimal color value string
* as a value argument.
*/
ForeColor = "foreColor",
/**
* Adds an HTML block-level element around the line containing the current selection, replacing the block element containing
* the line if one exists (in Firefox, <blockquote> is the exception — it will wrap any containing block element).
* Requires a tag-name string as a value argument. Virtually all block-level elements can be used.
* (Internet Explorer supports only heading tags H1–H6, ADDRESS, and PRE, which must be wrapped in angle brackets, such as "<H1>".)
*/
FormatBlock = "formatBlock",
/**
* Deletes the character ahead of the cursor's position, identical to hitting the Delete key on a Windows keyboard.
*/
ForwardDelete = "forwardDelete",
/**
* Adds a heading element around a selection or insertion point line. Requires the tag-name stringas a value argument (i.e. "H1", "H6").
* (Not supported by Internet Explorer and Safari.)
*/
Heading = "heading",
/**
* Changes the background color for the selection or at the insertion point. Requires a color value string as a value argument.
* useCSS must be true for this to function. (Not supported by Internet Explorer.)
*/
HiliteColor = "hiliteColor",
/**
* Adds a <big> tag around the selection or at the insertion point. (Not supported by Internet Explorer.)
*/
IncreaseFontSize = "increaseFontSize",
/**
* Indents the line containing the selection or insertion point. In Firefox, if the selection spans multiple lines at different
* levels of indentation, only the least indented lines in the selection will be indented.
*/
Indent = "indent",
/**
* Controls whether the Enter key inserts a <br> element, or splits the current block element into two.
* (Not supported by Internet Explorer.)
*/
InsertBrOnReturn = "insertBrOnReturn",
/**
* Inserts a <hr> element at the insertion point, or replaces the selection with it.
*/
InsertHorizontalRule = "insertHorizontalRule",
/**
* Inserts an HTML string at the insertion point (deletes selection). Requires a valid HTML string as a value argument.
* (Not supported by Internet Explorer.)
*/
InsertHTML = "insertHTML",
/**
* Inserts an image at the insertion point (deletes selection). Requires a URL string for the image's src as a value argument.
* The requirements for this string are the same as createLink.
*/
InsertImage = "insertImage",
/**
* Creates a numbered ordered list for the selection or at the insertion point.
*/
InsertOrderedList = "insertOrderedList",
/**
* Creates a bulleted unordered list for the selection or at the insertion point.
*/
InsertUnorderedList = "insertUnorderedList",
/**
* Inserts a paragraph around the selection or the current line.
* (Internet Explorer inserts a paragraph at the insertion point and deletes the selection.)
*/
InsertParagraph = "insertParagraph",
/**
* Inserts the given plain text at the insertion point (deletes selection).
*/
InsertText = "insertText",
/**
* Toggles italics on/off for the selection or at the insertion point.
* (Internet Explorer uses the <em> element instead of <i>.)
*/
Italic = "italic",
/**
* Centers the selection or insertion point.
*/
JustifyCenter = "justifyCenter",
/**
* Justifies the selection or insertion point.
*/
JustifyFull = "justifyFull",
/**
* Justifies the selection or insertion point to the left.
*/
JustifyLeft = "justifyLeft",
/**
* Right-justifies the selection or the insertion point.
*/
JustifyRight = "justifyRight",
/**
* Outdents the line containing the selection or insertion point.
*/
Outdent = "outdent",
/**
* Pastes the clipboard contents at the insertion point (replaces current selection). Disabled for web content. See [1].
*/
Paste = "paste",
/**
* Redoes the previous undo command.
*/
Redo = "redo",
/**
* Removes all formatting from the current selection.
*/
RemoveFormat = "removeFormat",
/**
* Selects all of the content of the editable region.
*/
SelectAll = "selectAll",
/**
* Toggles strikethrough on/off for the selection or at the insertion point.
*/
StrikeThrough = "strikeThrough",
/**
* Toggles subscript on/off for the selection or at the insertion point.
*/
Subscript = "subscript",
/**
* Toggles superscript on/off for the selection or at the insertion point.
*/
Superscript = "superscript",
/**
* Toggles underline on/off for the selection or at the insertion point.
*/
Underline = "underline",
/**
* Undoes the last executed command.
*/
Undo = "undo",
/**
* Removes the anchor element from a selected hyperlink.
*/
Unlink = "unlink",
/**
* Replaces the useCSS command. true modifies/generates style attributes in markup, false generates presentational elements.
*/
StyleWithCSS = "styleWithCSS"
}
/**
* The is essentially an enum representing result from browser compareDocumentPosition API
* https: */
export const enum DocumentPosition {
/**
* Same node
*/
Same = 0,
/**
* Node is disconnected from document
*/
Disconnected = 1,
/**
* Node is preceding the comparing node
*/
Preceding = 2,
/**
* Node is following the comparing node
*/
Following = 4,
/**
* Node contains the comparing node
*/
Contains = 8,
/**
* Node is contained by the comparing node
*/
ContainedBy = 16
}
/**
* The is essentially an enum represents the type of the node
* https: * Values not listed here are deprecated.
*/
export const enum NodeType {
/**
* An Element node such as <p> or <div>.
*/
Element = 1,
/**
* The actual Text of Element or Attr.
*/
Text = 3,
/**
* A ProcessingInstruction of an XML document such as <?xml-stylesheet ... ?> declaration.
*/
ProcessingInstruction = 7,
/**
* A Comment node.
*/
Comment = 8,
/**
* A Document node.
*/
Document = 9,
/**
* A DocumentType node e.g. <!DOCTYPE html> for HTML5 documents.
*/
DocumentType = 10,
/**
* A DocumentFragment node.
*/
DocumentFragment = 11
}
/**
* enum for setting block alignment, used by setAlignment API
*/
export const enum Alignment {
/**
* Align left
*/
Left = 0,
/**
* Align center
*/
Center = 1,
/**
* Align right
*/
Right = 2
}
/**
* Possible change sources. Here are the predefined sources.
* It can also be other string if the change source can't fall into these sources.
*/
export const enum ChangeSource {
/**
* Content changed by auto link
*/
AutoLink = "AutoLink",
/**
* Content changed by create link
*/
CreateLink = "CreateLink",
/**
* Content changed by format
*/
Format = "Format",
/**
* Content changed by image resize
*/
ImageResize = "ImageResize",
/**
* Content changed by paste
*/
Paste = "Paste",
/**
* Content changed by setContent API
*/
SetContent = "SetContent",
/**
* Content changed by cut operation
*/
Cut = "Cut",
/**
* Content changed by drag & drop operation
*/
Drop = "Drop",
/**
* Insert a new entity into editor
*/
InsertEntity = "InsertEntity"
}
/**
* The position. Mostly used for content insertion and traversing
* On insertion, we will need to specify where we want the content to be placed (begin, end, selection or outside)
* On content traversing, we will need to specify the start position of traversing
*/
export const enum ContentPosition {
/**
* Begin of the container
*/
Begin = 0,
/**
* End of the container
*/
End = 1,
/**
* End of the content div domain.
*/
DomEnd = 2,
/**
* Selection start
*/
SelectionStart = 3,
/**
* Outside of editor
*/
Outside = 4,
/**
* Manually defined range
*/
Range = 5
}
/**
* enum for setting block direction, used by setDirection API
*/
export const enum Direction {
/**
* Left to right
*/
LeftToRight = 0,
/**
* Right to left
*/
RightToLeft = 1
}
/**
* Define possible operations to an entity
*/
export const enum EntityOperation {
/**
* Notify plugins that there is a new plugin was added into editor.
* Plugin can handle this event to entity hydration.
* This event will be only fired once for each entity DOM node.
* After undo, or copy/paste, since new DOM nodes were added, this event will be fired
* for those entites represented by newly added nodes.
*/
NewEntity = 0,
/**
* Notify plugins that user is clicking target to an entity
*/
Click = 1,
/**
* Notify plugins that user is triggering context menu to an entity
*/
ContextMenu = 2,
/**
* Notify plugins that user is escaping from an entity by pressing ESC key
*/
Escape = 3,
/**
* Notify plugins that user is removing an entity from its start position using DELETE key
*/
RemoveFromStart = 4,
/**
* Notify plugins that user is remove an entity from its end position using BACKSPACE key
*/
RemoveFromEnd = 5,
/**
* Notify plugins that an entity is being overwritten.
* This can be causes by key in, cut, paste, delete, backspace ... on a selection
* which contains some entites.
*/
Overwrite = 6,
/**
* Notify plugins that an entity is being partially overwritten.
* This happens when user selected part of the entity then do key press, or cut, paste, delete, backspace, ...
*/
PartialOverwrite = 7,
/**
* Notify plugins that editor is generating HTML content for save.
* Plugin should use this event to remove any temporary content, and only leave DOM nodes that
* should be saved as HTML string.
* This event will provide a cloned DOM tree for each entity, do NOT compare the DOM nodes with cached nodes
* because it will always return false.
*/
ReplaceTemporaryContent = 8
}
/**
* The enum used for increase or decrease font size
* Used by setFontSize API
*/
export const enum FontSizeChange {
/**
* Increase font size
*/
Increase = 0,
/**
* Decrease font size
*/
Decrease = 1
}
/**
* The enum used for increase or decrease indentation of a block
* Used by setIndentation API
*/
export const enum Indentation {
/**
* Increase indentation
*/
Increase = 0,
/**
* Decrease indentation
*/
Decrease = 1
}
/**
* Type of list (numbering or bullet)
*/
export const enum ListType {
/**
* None list type
* It means this is not a list
*/
None = 0,
/**
* Ordered List type (numbering list)
* Represented by "OL" tag
*/
Ordered = 1,
/**
* Unordered List type (bullet list)
* Represented by "UL" tag
*/
Unordered = 2
}
/**
* Paste option
*/
export const enum PasteOption {
/**
* Paste html with content type "text/html"
*/
PasteHtml = 0,
/**
* Paste plain text with content type "text/plain"
*/
PasteText = 1,
/**
* Paste image from clipboard with content type "image/*"
*/
PasteImage = 2
}
/**
* Represent the type of a position
*/
export const enum PositionType {
/**
* At the begninning of a node
*/
Begin = 0,
/**
* At the endo of a node
*/
End = -1,
/**
* Before a node
*/
Before = -2,
/**
* After a node
*/
After = -3
}
/**
* Query scope for queryElements() API
*/
export const enum QueryScope {
/**
* Query from the whole body of root node. This is default value.
*/
Body = 0,
/**
* Query elements on a given selction (intersect)
* The result element can contain the selection, contain part of selection, or inside selection
*/
OnSelection = 1,
/**
* Query elements inside a given selection only
*/
InSelection = 2
}
/**
* Type of all possible regions. Currently we only support region of Table
*/
export const enum RegionType {
/**
* Region splitted by Table
*/
Table = 0
}
/**
* Operations used by editTable() API
*/
export const enum TableOperation {
/**
* Insert a row above current row
*/
InsertAbove = 0,
/**
* Insert a row below current row
*/
InsertBelow = 1,
/**
* Insert a column on the left of current column
*/
InsertLeft = 2,
/**
* Insert a column on the right of current column
*/
InsertRight = 3,
/**
* Delete the whole table
*/
DeleteTable = 4,
/**
* Delete current column
*/
DeleteColumn = 5,
/**
* Delete current row
*/
DeleteRow = 6,
/**
* Merge current row with the row above
*/
MergeAbove = 7,
/**
* Merge current row with the row below
*/
MergeBelow = 8,
/**
* Merge current column with the column on the left
*/
MergeLeft = 9,
/**
* Merge current column with the column on the right
*/
MergeRight = 10,
/**
* Split current table cell horizontally
*/
SplitHorizontally = 11,
/**
* Split current table cell vertically
*/
SplitVertically = 12
}
/**
* Editor plugin event interface
*/
export interface BasePluginEvent<T extends PluginEventType> {
/**
* Type of this event
*/
eventType: T;
/**
* An optional event cache.
* This will be consumed by event cache API to store some expensive calculation result.
* So that for the same event across plugins, the result doesn't need to be calculated again
*/
eventDataCache?: {
[key: string]: any;
};
}
/**
* Provides a chance for plugin to change the content before it is pasted into editor.
*/
export interface BeforeDisposeEvent extends BasePluginEvent<PluginEventType.BeforeDispose> {
}
/**
* Provides a chance for plugin to change the content before it is pasted into editor.
*/
export interface BeforePasteEvent extends BasePluginEvent<PluginEventType.BeforePaste> {
/**
* An object contains all related data for pasting
*/
clipboardData: ClipboardData;
/**
* HTML Document Fragment which will be inserted into content if pasteOption is set to PasteHtml
*/
fragment: DocumentFragment;
/**
* Paste option: html, text or image
*/
pasteOption: PasteOption;
}
/**
* Represents a change to the editor made by another plugin
*/
export interface ContentChangedEvent extends BasePluginEvent<PluginEventType.ContentChanged> {
/**
* Source of the change
*/
source: ChangeSource | string;
/**
* Optional related data
*/
data?: any;
}
/**
* Provides a chance for plugin to change the content before it is pasted into editor.
*/
export interface EditorReadyEvent extends BasePluginEvent<PluginEventType.EditorReady> {
}
/**
* Provide a chance for plugins to handle entity related events.
* See enum EntityOperation for more details about each operation
*/
export interface EntityOperationEvent extends BasePluginEvent<PluginEventType.EntityOperation> {
/**
* Operation to this entity
*/
operation: EntityOperation;
/**
* The entity that editor is operating on
*/
entity: Entity;
/**
* Optional raw UI event. Need to do null check before use its value
*/
rawEvent?: UIEvent;
}
/**
* @deprecated Use ExtractContentWithDomEvent instead
* Represents a custom BasePluginEvent for extracting content
*/
export interface ExtractContentEvent extends BasePluginEvent<PluginEventType.ExtractContent> {
/**
* Current content string
* Plugin can change this string to clean up the markups it added before
*/
content: string;
}
/**
* Extract Content with a DOM tree event
* This event is triggered when getContent() is called with triggerExtractContentEvent = true
* Plugin can handle this event to remove the UI only markups to return clean HTML
* by operating on a cloned DOM tree
*/
export interface ExtractContentWithDomEvent extends BasePluginEvent<PluginEventType.ExtractContentWithDom> {
/**
* Cloned root element of editor
* Plugin can change this DOM tree to clean up the markups it added before
*/
clonedRoot: HTMLElement;
}
/**
* An event fired when pending format state (bold, italic, underline, ... with collapsed selection) is changed
*/
export interface PendingFormatStateChangedEvent extends BasePluginEvent<PluginEventType.PendingFormatStateChanged> {
formatState: PendableFormatState;
}
/**
* This represents a PluginEvent wrapping native browser event
*/
export type PluginDomEvent = PluginCompositionEvent | PluginMouseEvent | PluginKeyboardEvent | PluginInputEvent | PluginScrollEvent;
/**
* This represents a PluginEvent wrapping native CompositionEnd event
*/
export interface PluginCompositionEvent extends BasePluginEvent<PluginEventType.CompositionEnd> {
rawEvent: CompositionEvent;
}
/**
* The represents a PluginEvent wrapping native Keyboard event
*/
export type PluginKeyboardEvent = PluginKeyDownEvent | PluginKeyPressEvent | PluginKeyUpEvent;
/**
* This represents a PluginEvent wrapping native KeyDown event
*/
export interface PluginKeyDownEvent extends BasePluginEvent<PluginEventType.KeyDown> {
rawEvent: KeyboardEvent;
}
/**
* This represents a PluginEvent wrapping native KeyPress event
*/
export interface PluginKeyPressEvent extends BasePluginEvent<PluginEventType.KeyPress> {
rawEvent: KeyboardEvent;
}
/**
* This represents a PluginEvent wrapping native KeyUp event
*/
export interface PluginKeyUpEvent extends BasePluginEvent<PluginEventType.KeyUp> {
rawEvent: KeyboardEvent;
}
/**
* This represents a PluginEvent wrapping native Mouse event
*/
export type PluginMouseEvent = PluginMouseDownEvent | PluginMouseUpEvent;
/**
* This represents a PluginEvent wrapping native MouseDown event
*/
export interface PluginMouseDownEvent extends BasePluginEvent<PluginEventType.MouseDown> {
rawEvent: MouseEvent;
}
/**
* This represents a PluginEvent wrapping native MouseUp event
*/
export interface PluginMouseUpEvent extends BasePluginEvent<PluginEventType.MouseUp> {
rawEvent: MouseEvent;
}
/**
* This represents a PluginEvent wrapping native input / textinput event
*/
export interface PluginInputEvent extends BasePluginEvent<PluginEventType.Input> {
rawEvent: InputEvent;
}
export interface PluginScrollEvent extends BasePluginEvent<PluginEventType.Scroll> {
rawEvent: UIEvent;
scrollContainer: HTMLElement;
}
/**
* Editor plugin event interface
*/
export type PluginEvent = BeforePasteEvent | ContentChangedEvent | EntityOperationEvent | ExtractContentEvent | ExtractContentWithDomEvent | PluginDomEvent | EditorReadyEvent | BeforeDisposeEvent | PendingFormatStateChangedEvent | DarkModeChangedEvent;
/**
* Editor plugin event type
*/
export const enum PluginEventType {
/**
* HTML KeyDown event
*/
KeyDown = 0,
/**
* HTML KeyPress event
*/
KeyPress = 1,
/**
* HTML KeyUp event
*/
KeyUp = 2,
/**
* HTML CompositionEnd event
*/
CompositionEnd = 3,
/**
* HTML MouseDown event
*/
MouseDown = 4,
/**
* HTML MouseUp event
*/
MouseUp = 5,
/**
* Content changed event
*/
ContentChanged = 6,
/**
* @deprecated Use ExtractContentWithDom instead.
* Extract Content event
* This event is triggered when getContent() is called with triggerExtractContentEvent = true
* Plugin can handle this event to remove the UI only markups to return clean HTML
*/
ExtractContent = 7,
/**
* Extract Content with a DOM tree event
* This event is triggered when getContent() is called with triggerExtractContentEvent = true
* Plugin can handle this event to remove the UI only markups to return clean HTML
* by operating on a cloned DOM tree
*/
ExtractContentWithDom = 8,
/**
* Before Paste event, provide a chance to change paste content
*/
BeforePaste = 9,
/**
* Let plugin know editor is ready now
*/
EditorReady = 10,
/**
* Let plugin know editor is about to dispose
*/
BeforeDispose = 11,
/**
* HTML Input / TextInput event
*/
Input = 12,
/**
* Pending format state (bold, italic, underline, ... with collapsed selection) is changed
*/
PendingFormatStateChanged = 13,
/**
* Dark mode state is changed
*/
DarkModeChanged = 14,
/**
* Scroll event triggered by scroll container
*/
Scroll = 15,
/**
* Operating on an entity. See enum EntityOperation for more details about each operation
*/
EntityOperation = 16
}
/**
* A type to extract data part of a plugin event type. Data part is the plugin event without eventType field.
*/
export type PluginEventData<T extends PluginEventType> = PluginEventDataGeneric<PluginEvent, T>;
/**
* A type to extract data part of a plugin event type. Data part is the plugin event without eventType field.
* This type is a middle result and only used by PluginEventData type
*/
export type PluginEventDataGeneric<E extends PluginEvent, T extends PluginEventType> = E extends BasePluginEvent<T> ? Pick<E, Exclude<keyof E, 'eventType'>> : never;
/**
* A type to get specify plugin event type from eventType parameter.
*/
export type PluginEventFromType<T extends PluginEventType> = PluginEventFromTypeGeneric<PluginEvent, T>;
/**
* A type to get specify plugin event type from eventType parameter.
* This type is a middle result and only used by PluginEventFromType type
*/
export type PluginEventFromTypeGeneric<E extends PluginEvent, T extends PluginEventType> = E extends BasePluginEvent<T> ? E : never;
export interface DarkModeChangedEvent extends BasePluginEvent<PluginEventType.DarkModeChanged> {
changedToDarkMode: boolean;
}
/**
* This refers to a "content block" in editor that serves as a content parsing boundary
* It is most those html block like tags, i.e. <p>, <div>, <li>, <td> etc.
* but can also be just a text node, followed by a <br>, i.e.
* for html fragment <div>abc<br>123</div>, abc<br> is a block, 123 is another block
*/
export interface BlockElement {
/**
* Collapse this block element to a single DOM element.
*/
collapseToSingleElement(): HTMLElement;
/**
* Get start node of this block element
*/
getStartNode(): Node;
/**
* Get end node of this block element
*/
getEndNode(): Node;
/**
* Check whether this block element equals to the given block element
*/
equals(blockElement: BlockElement): boolean;
/**
* Checks if this block element is after another block element
*/
isAfter(blockElement: BlockElement): boolean;
/**
* Check if the given node is within this block element
*/
contains(node: Node): boolean;
/**
* Get the text content of this block element
*/
getTextContent(): string;
}
/**
* An object contains all related data for pasting
*/
export interface ClipboardData {
/**
* An editor content snapshot before pasting happens. This is used for changing paste format
*/
snapshotBeforePaste: string;
/**
* The format state at cursor before pasting. This is used for changing paste format
*/
originalFormat: DefaultFormat;
/**
* Types of content included by the original onpaste event
*/
types: string[];
/**
* If the copied data contains image format, this will be the image blob. Otherwise it is null.
*/
image: File;
/**
* If the copied data contains plain text format, this will be the plain text string. Otherwise it is null.
*/
text: string;
/**
* If the copied data contains HTML format, this will be the sanitized html string. Otherwise it is null.
*/
html: string;
/**
* If the copied data contains HTML format, this will be the original html string without any processing. Otherwise it is null.
*/
rawHtml: string;
}
/**
* Represents items retrieved from clipboard event
*/
export interface ClipboardItems {
/**
* Available types from clipboard event
*/
types: string[];
/**
* Plain text from clipboard event
*/
text: string;
/**
* HTML string from clipboard event.
* When set to null, it means there's no HTML from clipboard event.
* When set to undefined, it means there may be HTML in clipboard event, but fail to retrieve
*/
html: string;
/**
* Image file from clipboard event
*/
image: File;
}
/**
* The options to specify dark mode editor behavior
*/
export interface DarkModeOptions {
/** Transform on insert controls if, when the editor is initialized, content should be transformed for dark mode.
* Set this to true to run the content being set to the editor through an initial transform into dark mode.
* Set this to false if you are setting dark mode compliant content initialy.
*/
transformOnInitialize?: boolean;
/**
* RoosterJS provides an experemental "external content handler" that transforms text
* This is used when content is pasted or inserted via a method we can hook into.
* This transform is currently "lossy" and will eliminate color information.
* If you want change this behavior, you may define a different function here.
* It takes in the impacted HTMLElement
*/
onExternalContentTransform?: (htmlIn: HTMLElement) => void;
}
/**
* Default format settings
*/
export interface DefaultFormat {
/**
* Font family
*/
fontFamily?: string;
/**
* Font size
*/
fontSize?: string;
/**
* Single text color (for non dark mode/single mode editor)
*/
textColor?: string;
/**
* Text color light/dark mode pair
*/
textColors?: ModeIndependentColor;
/**
* Single background color (for non dark mode/single mode editor)
*/
backgroundColor?: string;
/**
* Background color light/dark mode pair
*/
backgroundColors?: ModeIndependentColor;
/**
* Whether is bold
*/
bold?: boolean;
/**
* Whether is italic
*/
italic?: boolean;
/**
* Whether has underline
*/
underline?: boolean;
}
/**
* Represents an entity in editor.
* An entity is an HTML element with special CSS classes and will be treated as an atom from the editor.
* Editor provides basic operations and will trigger related events to let plugins know that there is
* operation target to an entity.
* Plugin can insert/remove an entity, handle entity events, query entities within the editor.
* Plugin can also set an entity to be readonly so that user can't modify content within an entity.
*/
export interface Entity {
/**
* Type of this entity. Specified when insert an entity, can be an valid CSS class-like string.
*/
type: string;
/**
* Id of this entity, generated by editor code and will be unique within an editor
*/
id: string;
/**
* The root DOM node of this entity
*/
contentNode: HTMLElement;
/**
* Whether this is a readonly entity
*/
isReadonly: boolean;
}
/**
* The format state
*/
export interface FormatState extends PendableFormatState, ElementBasedFormatState, StyleBasedFormatState {
/**
* @deprecated Use editor.canUndo() instead
* Whether the content can be undone
*/
canUndo?: boolean;
/**
* @deprecated Use editor.canRedo() instead
* Whether the content ca nbe redone
*/
canRedo?: boolean;
}
/**
* Format states that can have pending state.
*
* e.g., When using execCommand('bold') target to a collapsed selection, browser will enter bold state,
* but there isn't a <B> tag until user type something, or the state will be rollback if selection
* is changed.
*/
export interface PendableFormatState {
/**
* Whether the text is bolded
*/
isBold?: boolean;
/**
* Whether the text is italic
*/
isItalic?: boolean;
/**
* Whether the text has underline
*/
isUnderline?: boolean;
/**
* Whether the text has strike through line
*/
isStrikeThrough?: boolean;
/**
* Whether the text is in subscript mode
*/
isSubscript?: boolean;
/**
* Whether the text is in superscript mode
*/
isSuperscript?: boolean;
}
/**
* Format state represented by DOM element
*/
export interface ElementBasedFormatState {
/**
* Whether the text is in bullet mode
*/
isBullet?: boolean;
/**
* Whether the text is in numbering mode
*/
isNumbering?: boolean;
/**
* Whether the text is in block quote
*/
isBlockQuote?: boolean;
/**
* Whether unlink command can be called to the text
*/
canUnlink?: boolean;
/**
* Whether add image alt text command can be called to the text
*/
canAddImageAltText?: boolean;
/**
* Header level (0-6, 0 means no header)
*/
headerLevel?: number;
}
/**
* Format states represented by CSS style
*/
export interface StyleBasedFormatState {
/**
* Font name
*/
fontName?: string;
/**
* Font size
*/
fontSize?: string;
/**
* Background color
*/
backgroundColor?: string;
/**
* Text color
*/
textColor?: string;
}
/**
* This refers to an inline element (as opposed to block) in editor
* Inline and block makes the "type" system in editor.
* An inline element is a maximum resolvable "entity" within the boundary of a block
* At minimum and also most commonly, it represents a text node.
* It can represent broader "content" depending on the resolvers that are available, i.e.
* it can be anchor link, image, emoji, ...
* Two rules:
* 1) every inline element must have a container node (text or span, a etc.)
* 2) inline element cannot be nested
*/
export interface InlineElement {
/**
* Get the text content of this inline element
*/
getTextContent(): string;
/**
* Get the container node of this inline element
*/
getContainerNode(): Node;
/**
* Get the parent block element of this inline element
*/
getParentBlock(): BlockElement;
/**
* Get the start position of this inline element
*/
getStartPosition(): NodePosition;
/**
* Get the end position of this inline element
*/
getEndPosition(): NodePosition;
/**
* Checks if the given inline element is after this inline element
*/
isAfter(inlineElement: InlineElement): boolean;
/**
* Checks if this inline element is a textual inline element
*/
isTextualInlineElement(): boolean;
/**
* Checks if the given editor position is contained in this inline element
*/
contains(position: NodePosition): boolean;
/**
* Apply inline style to a region of an inline element
*/
applyStyle(styler: (element: HTMLElement, isInnerNode?: boolean) => any): void;
}
/**
* Type definition for the InsertOption, used in the insertNode API.
* The position parameter defines how the node will be inserted.
* In a future revision, this will become strongly typed
* Only parameters applicable to the given position will be accepted.
*/
export type InsertOption = InsertOptionRange | InsertOptionBasic;
/**
* Shared options for insertNode related APIs
*/
export interface InsertOptionBase {
/**
* Whether need to update cursor.
*/
updateCursor?: boolean;
/**
* Boolean flag for inserting the content onto a new line.
* No-op for ContentPosition.Outside
*/
insertOnNewLine?: boolean;
/**
* Boolean flag for inserting the content onto a new line.
* No-op for ContentPosition.Begin, End, and Outside
*/
replaceSelection?: boolean;
}
/**
* The "basic" insertNode related ContentPositions that require no additional parameters to use.
*/
export interface InsertOptionBasic extends InsertOptionBase {
position: ContentPosition.Begin | ContentPosition.End | ContentPosition.DomEnd | ContentPosition.Outside | ContentPosition.SelectionStart;
}
/**
* The Range varient where insertNode will opperate on a range disjointed from the current selection state.
*/
export interface InsertOptionRange extends InsertOptionBase {
position: ContentPosition.Range;
/**
* The range to be targeted when insertion happens.
*/
range: Range;
}
/**
* LinkData represents a link match result
*/
export interface LinkData {
/**
* Schema of a hyperlink
*/
scheme: string;
/**
* Original url of a hyperlink
*/
originalUrl: string;
/**
* Normalized url of a hyperlink
*/
normalizedUrl: string;
}
export interface ModeIndependentColor {
/**
* The color to be used in dark mode, if enabled.
*/
darkModeColor: string;
/**
* The color to be used in light mode, or stored as the original color in dark mode.
*/
lightModeColor: string;
}
/**
* Represent a position in DOM tree by the node and its offset index
*/
export interface NodePosition {
readonly node: Node;
readonly element: HTMLElement;
readonly offset: number;
readonly isAtEnd: boolean;
/**
* Normalize this position to the leaf node, return the normalize result.
* If current position is already using leaf node, return this position object itself
*/
normalize(): NodePosition;
/**
* Check if this position is equal to the given position
* @param position The position to check
*/
equalTo(position: NodePosition): boolean;
/**
* Checks if this position is after the given position
* @param position The position to check
*/
isAfter(position: NodePosition): boolean;
/**
* Move this position with offset, returns a new position with a valid offset in the same node
* @param offset Offset to move with
*/
move(offset: number): NodePosition;
}
/**
* This represents a rect inside editor
*/
export interface Rect {
/**
* Top
*/
top: number;
/**
* Bottom
*/
bottom: number;
/**
* Left
*/
left: number;
/**
* Right
*/
right: number;
}
/**
* Represents a DOM region.
* A region is a range under a given node, and possibly after one child and before another child
* e.g.
* ```html
* <div>
* <table>...</table>
* <span>...</span>
* <span>...</span>
* <table>...</table>
* <div>
* ```
* We can define a region under DIV before the second TABLE and after the first TABLE
*
* This is used when user's selection go across different TD elements or start from TD and end after
* that TD (or inverse way). Some block operation should not ruin the TABLE structure, so we need to
* split the selection into several regions.
*/
export interface Region {
/**
* Root node of this region
*/
rootNode: HTMLElement;
/**
* A node to define the beginning boundary of this region.
* All nodes after this node before nodeAfter and contaiend by rootNode will be treated contained by this region.
*/
nodeBefore: Node;
/**
* A node to define the ending boundary of this region.
* All nodes before this node after nodeBefore and contaiend by rootNode will be treated contained by this region.
*/
nodeAfter: Node;
/**
* Tags that child elements will be skipped
*/
skipTags: string[];
/**
* Start position of full selection. It is possible to be out of this region.
* We use this position and fullSelectionEnd to calculate the selected range inside this region.
*/
fullSelectionStart: NodePosition;
/**
* End position of full selection. It is possible to be out of this region.
* We use this position and fullSelectionStart to calculate the selected range inside this region.
*/
fullSelectionEnd: NodePosition;
}
/**
* A start and end pair of selection path
*/
export interface SelectionPath {
/**
* Start path of selection
*/
start: number[];
/**
* End path of selection
*/
end: number[];
}
/**
* Represents a data structure of snapshots, this is usually used for undo snapshots
*/
export interface Snapshots {
/**
* The snapshot array
*/
snapshots: string[];
/**
* Size of all snapshots
*/
totalSize: number;
/**
* Current index
*/
currentIndex: number;
/**
* Max size of all snapshots
*/
readonly maxSize: number;
}
/**
* Table format
*/
export interface TableFormat {
/**
* Background color for even rows
*/
bgColorEven: string;
/**
* Background color for odd rows
*/
bgColorOdd: string;
/**
* Top border color for each row
*/
topBorderColor: string;
/**
* Bottom border color for each row
*/
bottomBorderColor: string;
/**
* Vertical border color for each row
*/
verticalBorderColor: string;
}
/**
* Options for HtmlSanitizer
*/
export interface HtmlSanitizerOptions {
/**
* Callbacks for HTML elements
*/
elementCallbacks?: ElementCallbackMap;
/**
* Callbacks for HTML attributes
*/
attributeCallbacks?: AttributeCallbackMap;
/**
* Callbacks for CSS styles
*/
styleCallbacks?: StyleCallbackMap;
/**
* Allowed HTML tags in addition to default tags, in upper case
*/
additionalAllowedTags?: string[];
/**
* Allowed HTML attributes in addition to default attributes, in lower case
* TODO: rename to "additionalAllowedAttributes" in next major release
*/
additionalAllowAttributes?: string[];
/**
* Allowed CSS Class names
*/
additionalAllowedCssClasses?: string[];
/**
* CSS style default values in addition to the default value map, style name should be in lower case
*/
additionalDefaultStyleValues?: StringMap;
/**
* Additional global CSS style nodes
*/
additionalGlobalStyleNodes?: HTMLStyleElement[];
/**
* Whether allow CSS white-space in result
*/
allowPreserveWhiteSpace?: boolean;
}
/**
* Options for sanitizeHtml function
*/
export interface SanitizeHtmlOptions extends HtmlSanitizerOptions {
/**
* Current HTML element, styles of this element will be used as current style values.
* Or a string map represents current styles
*/
currentElementOrStyle?: HTMLElement | StringMap;
/**
* When set to true, will only do inline CSS conversion and skip the sanitizing pass
*/
convertCssOnly?: boolean;
/**
* When set to true, only content inside Fragment markup (if any) will be preserved
*/
preserveFragmentOnly?: boolean;
}
/**
* Define DOM types of window, used by safeInstanceOf() to check if a given object is of the specified type of its own window
*
* !!!Note: This file is generated from /tools/generateTargetWindow.js. Do NOT modify this file directly!!!
*/
export interface TargetWindow {
Range: Range;
Node: Node;
Element: Element;
SVGElement: SVGElement;
SVGViewElement: SVGViewElement;
SVGTitleElement: SVGTitleElement;
SVGSymbolElement: SVGSymbolElement;
SVGStyleElement: SVGStyleElement;
SVGStopElement: SVGStopElement;
SVGScriptElement: SVGScriptElement;
SVGPatternElement: SVGPatternElement;
SVGMetadataElement: SVGMetadataElement;
SVGMaskElement: SVGMaskElement;
SVGMarkerElement: SVGMarkerElement;
SVGGraphicsElement: SVGGraphicsElement;
SVGUseElement: SVGUseElement;
SVGTextContentElement: SVGTextContentElement;
SVGTextPositioningElement: SVGTextPositioningElement;
SVGTextElement: SVGTextElement;
SVGTSpanElement: SVGTSpanElement;
SVGTextPathElement: SVGTextPathElement;
SVGSwitchElement: SVGSwitchElement;
SVGSVGElement: SVGSVGElement;
SVGPathElement: SVGPathElement;
SVGImageElement: SVGImageElement;
SVGGeometryElement: SVGGeometryElement;
SVGRectElement: SVGRectElement;
SVGPolylineElement: SVGPolylineElement;
SVGPolygonElement: SVGPolygonElement;
SVGLineElement: SVGLineElement;
SVGEllipseElement: SVGEllipseElement;
SVGCircleElement: SVGCircleElement;
SVGGElement: SVGGElement;
SVGForeignObjectElement: SVGForeignObjectElement;
SVGDefsElement: SVGDefsElement;
SVGAElement: SVGAElement;
SVGGradientElement: SVGGradientElement;
SVGRadialGradientElement: SVGRadialGradientElement;
SVGLinearGradientElement: SVGLinearGradientElement;
SVGFilterElement: SVGFilterElement;
SVGFETurbulenceElement: SVGFETurbulenceElement;
SVGFETileElement: SVGFETileElement;
SVGFESpotLightElement: SVGFESpotLightElement;
SVGFESpecularLightingElement: SVGFESpecularLightingElement;
SVGFEPointLightElement: SVGFEPointLightElement;
SVGFEOffsetElement: SVGFEOffsetElement;
SVGFEMorphologyElement: SVGFEMorphologyElement;
SVGFEMergeNodeElement: SVGFEMergeNodeElement;
SVGFEMergeElement: SVGFEMergeElement;
SVGFEImageElement: SVGFEImageElement;
SVGFEGaussianBlurElement: SVGFEGaussianBlurElement;
SVGFEFloodElement: SVGFEFloodElement;
SVGFEDropShadowElement: SVGFEDropShadowElement;
SVGFEDistantLightElement: SVGFEDistantLightElement;
SVGFEDisplacementMapElement: SVGFEDisplacementMapElement;
SVGFEDiffuseLightingElement: SVGFEDiffuseLightingElement;
SVGFEConvolveMatrixElement: SVGFEConvolveMatrixElement;
SVGFECompositeElement: SVGFECompositeElement;
SVGFEComponentTransferElement: SVGFEComponentTransferElement;
SVGFEColorMatrixElement: SVGFEColorMatrixElement;
SVGFEBlendElement: SVGFEBlendElement;
SVGDescElement: SVGDescElement;
SVGCursorElement: SVGCursorElement;
SVGComponentTransferFunctionElement: SVGComponentTransferFunctionElement;
SVGFEFuncRElement: SVGFEFuncRElement;
SVGFEFuncGElement: SVGFEFuncGElement;
SVGFEFuncBElement: SVGFEFuncBElement;
SVGFEFuncAElement: SVGFEFuncAElement;
SVGClipPathElement: SVGClipPathElement;
SVGAnimationElement: SVGAnimationElement;
SVGAnimateTransformElement: SVGAnimateTransformElement;
SVGAnimateMotionElement: SVGAnimateMotionElement;
SVGAnimateElement: SVGAnimateElement;
HTMLElement: HTMLElement;
HTMLUnknownElement: HTMLUnknownElement;
HTMLUListElement: HTMLUListElement;
HTMLTrackElement: HTMLTrackElement;
HTMLTitleElement: HTMLTitleElement;
HTMLTimeElement: HTMLTimeElement;
HTMLTextAreaElement: HTMLTextAreaElement;
HTMLTemplateElement: HTMLTemplateElement;
HTMLTableSectionElement: HTMLTableSectionElement;
HTMLTableRowElement: HTMLTableRowElement;
HTMLTableElement: HTMLTableElement;
HTMLTableColElement: HTMLTableColElement;
HTMLTableCellElement: HTMLTableCellElement;
HTMLTableHeaderCellElement: HTMLTableHeaderCellElement;
HTMLTableDataCellElement: HTMLTableDataCellElement;
HTMLTableCaptionElement: HTMLTableCaptionElement;
HTMLStyleElement: HTMLStyleElement;
HTMLSpanElement: HTMLSpanElement;
HTMLSourceElement: HTMLSourceElement;
HTMLSlotElement: HTMLSlotElement;
HTMLSelectElement: HTMLSelectElement;
HTMLScriptElement: HTMLScriptElement;
HTMLQuoteElement: HTMLQuoteElement;
HTMLProgressElement: HTMLProgressElement;
HTMLPreElement: HTMLPreElement;
HTMLPictureElement: HTMLPictureElement;
HTMLParamElement: HTMLParamElement;
HTMLParagraphElement: HTMLParagraphElement;
HTMLOutputElement: HTMLOutputElement;
HTMLOptionElement: HTMLOptionElement;
HTMLOptGroupElement: HTMLOptGroupElement;
HTMLObjectElement: HTMLObjectElement;
HTMLOListElement: HTMLOListElement;
HTMLModElement: HTMLModElement;
HTMLMeterElement: HTMLMeterElement;
HTMLMetaElement: HTMLMetaElement;
HTMLMenuElement: HTMLMenuElement;
HTMLMediaElement: HTMLMediaElement;
HTMLVideoElement: HTMLVideoElement;
HTMLAudioElement: HTMLAudioElement;
HTMLMarqueeElement: HTMLMarqueeElement;
HTMLMapElement: HTMLMapElement;
HTMLLinkElement: HTMLLinkElement;
HTMLLegendElement: HTMLLegendElement;
HTMLLabelElement: HTMLLabelElement;
HTMLLIElement: HTMLLIElement;
HTMLInputElement: HTMLInputElement;
HTMLImageElement: HTMLImageElement;
HTMLIFrameElement: HTMLIFrameElement;
HTMLHtmlElement: HTMLHtmlElement;
HTMLHeadingElement: HTMLHeadingElement;
HTMLHeadElement: HTMLHeadElement;
HTMLHRElement: HTMLHRElement;
HTMLFrameSetElement: HTMLFrameSetElement;
HTMLFrameElement: HTMLFrameElement;
HTMLFormElement: HTMLFormElement;
HTMLFontElement: HTMLFontElement;
HTMLFieldSetElement: HTMLFieldSetElement;
HTMLEmbedElement: HTMLEmbedElement;
HTMLDivElement: HTMLDivElement;
HTMLDirectoryElement: HTMLDirectoryElement;
HTMLDialogElement: HTMLDialogElement;
HTMLDetailsElement: HTMLDetailsElement;
HTMLDataListElement: HTMLDataListElement;
HTMLDataElement: HTMLDataElement;
HTMLDListElement: HTMLDListElement;
HTMLCanvasElement: HTMLCanvasElement;
HTMLButtonElement: HTMLButtonElement;
HTMLBodyElement: HTMLBodyElement;
HTMLBaseFontElement: HTMLBaseFontElement;
HTMLBaseElement: HTMLBaseElement;
HTMLBRElement: HTMLBRElement;
HTMLAreaElement: HTMLAreaElement;
HTMLAppletElement: HTMLAppletElement;
HTMLAnchorElement: HTMLAnchorElement;
DocumentType: DocumentType;
DocumentFragment: DocumentFragment;
ShadowRoot: ShadowRoot;
Document: Document;
XMLDocument: XMLDocument;
HTMLDocument: HTMLDocument;
ChildNode: ChildNode;
CharacterData: CharacterData;
Text: Text;
CDATASection: CDATASection;
ProcessingInstruction: ProcessingInstruction;
Comment: Comment;
Attr: Attr;
}
/**
* Attribute callback, will be called when HtmlSanitizer process an attribute with given name
* @param value Value of the attribute
* @param element The HTML element contains this attribute
* @param context A context object to store values which can used for communicating among callbacks
* @returns null to remove this attribute, otherwise keep the attribute with the value returned
*/
export type AttributeCallback = (value: string, element: HTMLElement, context: Object) => string;
/**
* A map of atttribute callbacks. Tag name should be in lower case
*/
export type AttributeCallbackMap = Record<string, AttributeCallback>;
/**
* Element callback, will be called when HtmlSanitizer process an element with the given tag
* @param element The HTML element
* @param context A context object to store values which can used for communicating among callbacks
* @returns True if this element should be kept, otherwise false
*/
export type ElementCallback = (element: HTMLElement, context: Object) => boolean;
/**
* A map of atttribute callbacks. Tag name should be in lower case
*/
export type StringMap = Record<string, string>;
/**
* Style callback, will be called when HtmlSanitizer process an inline CSS style with given name
* @param value Value of the CSS rule
* @param element The HTML element contains this CSS style
* @param context A context object to store values which can used for communicating among callbacks
* @returns True if this rule should be kept, otherwise false
*/
export type StyleCallback = (value: string, element: HTMLElement, context: Object) => boolean;
/**
* A map of style callbacks. Style name should be in lower case
*/
export type StyleCallbackMap = Record<string, StyleCallback>;
/**
* A map of elements callback. Tag name should be in upper case
*/
export type ElementCallbackMap = Record<string, ElementCallback>;
/**
* This presents a content block that can be reprented by a single html block type element.
* In most cases, it corresponds to an HTML block level element, i.e. P, DIV, LI, TD etc.
*/
export class NodeBlockElement implements BlockElement {
private element;
constructor(element: HTMLElement);
/**
* Collapse this element to a single DOM element.
* If the content nodes are separated in different root nodes, wrap them to a single node
* If the content nodes are included in root node with other nodes, split root node
*/
collapseToSingleElement(): HTMLElement;
/**
* Get the start node of the block
* For NodeBlockElement, start and end essentially refers to same node
*/
getStartNode(): Node;
/**
* Get the end node of the block
* For NodeBlockElement, start and end essentially refers to same node
*/
getEndNode(): Node;
/**
* Checks if it refers to same block
*/
equals(blockElement: BlockElement): boolean;
/**
* Checks if a block is after the current block
*/
isAfter(blockElement: BlockElement): boolean;
/**
* Checks if a certain html node is within the block
*/
contains(node: Node): boolean;
/**
* Get the text content of this block element
*/
getTextContent(): string;
}
/**
* This produces a block element from a a node
* It needs to account for various HTML structure. Examples:
* 1) <root><div>abc</div></root>
* This is most common the case, user passes in a node pointing to abc, and get back a block representing <div>abc</div>
* 2) <root><p><br></p></root>
* Common content for empty block, user passes node pointing to <br>, and get back a block representing <p><br></p>
* 3) <root>abc</root>
* Not common, but does happen. It is still a block in user's view. User passes in abc, and get back a start-end block representing abc
* NOTE: abc could be just one node. However, since it is not a html block, it is more appropriate to use start-end block although they point to same node
* 4) <root><div>abc<br>123</div></root>
* A bit tricky, but can happen when user use Ctrl+Enter which simply inserts a <BR> to create a link break. There're two blocks:
* block1: 1) abc<br> block2: 123
* 5) <root><div>abc<div>123</div></div></root>
* Nesting div and there is text node in same level as a DIV. Two blocks: 1) abc 2) <div>123</div>
* 6) <root><div>abc<span>123<br>456</span></div></root>
* This is really tricky. Essentially there is a <BR> in middle of a span breaking the span into two blocks;
* block1: abc<span>123<br> block2: 456
* In summary, given any arbitary node (leaf), to identify the head and tail of the block, following rules need to be followed:
* 1) to identify the head, it needs to crawl DOM tre left/up till a block node or BR is encountered
* 2) same for identifying tail
* 3) should also apply a block ceiling, meaning as it crawls up, it should stop at a block node
* @param rootNode Root node of the scope, the block element will be inside of this node
* @param node The node to get BlockElement start from
*/
export function getBlockElementAtNode(rootNode: Node, node: Node): BlockElement;
/**
* Get the first/last BlockElement of under the root node.
* If no suitable BlockElement found, returns null
* @param rootNode The root node to get BlockElement from
* @param isFirst True to get first BlockElement, false to get last BlockElement
*/
export function getFirstLastBlockElement(rootNode: Node, isFirst: boolean): BlockElement;
/**
* This reprents a block that is identified by a start and end node
* This is for cases like <root>Hello<BR>World</root>
* in that case, Hello<BR> is a block, World is another block
* Such block cannot be represented by a NodeBlockElement since they don't chained up
* to a single parent node, instead they have a start and end
* This start and end must be in same sibling level and have same parent in DOM tree
*/
export class StartEndBlockElement implements BlockElement {
private rootNode;
private startNode;
private endNode;
constructor(rootNode: Node, startNode: Node, endNode: Node);
static getBlockContext(node: Node): HTMLElement;
/**
* Collapse this element to a single DOM element.
* If the content nodes are separated in different root nodes, wrap them to a single node
* If the content nodes are included in root node with other nodes, split root node
*/
collapseToSingleElement(): HTMLElement;
/**
* Gets the start node
*/
getStartNode(): Node;
/**
* Gets the end node
*/
getEndNode(): Node;
/**
* Checks equals of two blocks
*/
equals(blockElement: BlockElement): boolean;
/**
* Checks if another block is after this current
*/
isAfter(blockElement: BlockElement): boolean;
/**
* Checks if an Html node is contained within the block
*/
contains(node: Node): boolean;
/**
* Get the text content of this block element
*/
getTextContent(): string;
}
/**
* The provides traversing of content inside editor.
* There are two ways to traverse, block by block, or inline element by inline element
* Block and inline traversing is independent from each other, meanning if you traverse block by block, it does not change
* the current inline element position
*/
export class ContentTraverser {
private scoper;
private skipTags?;
private currentInline;
private currentBlock;
/**
* Create a content traverser for the whole body of given root node
* @param scoper Traversing scoper object to help scope the traversing
* @param skipTags (Optional) tags that child elements will be skipped
*/
private constructor();
/**
* Create a content traverser for the whole body of given root node
* @param rootNode The root node to traverse in
* @param startNode The node to start from. If not passed, it will start from the beginning of the body
* @param skipTags (Optional) tags that child elements will be skipped
*/
static createBodyTraverser(rootNode: Node, startNode?: Node, skipTags?: string[]): ContentTraverser;
/**
* Create a content traverser for the given selection
* @param rootNode The root node to traverse in
* @param range The selection range to scope the traversing
* @param skipTags (Optional) tags that child elements will be skipped
*/
static createSelectionTraverser(rootNode: Node, range: Range, skipTags?: string[]): ContentTraverser;
/**
* Create a content traverser for a block element which contains the given position
* @param rootNode The root node to traverse in
* @param position A position inside a block, traversing will be scoped within this block.
* If passing a range, the start position of this range will be used
* @param startFrom Start position of traversing. The value can be Begin, End, SelectionStart
* @param skipTags (Optional) tags that child elements will be skipped
*/
static createBlockTraverser(rootNode: Node, position: NodePosition | Range, start?: ContentPosition, skipTags?: string[]): ContentTraverser;
/**
* Get current block
*/
get currentBlockElement(): BlockElement;
/**
* Get next block element
*/
getNextBlockElement(): BlockElement;
/**
* Get previous block element
*/
getPreviousBlockElement(): BlockElement;
private getPreviousNextBlockElement;
/**
* Current inline element getter
*/
get currentInlineElement(): InlineElement;
/**
* Get next inline element
*/
getNextInlineElement(): InlineElement;
/**
* Get previous inline element
*/
getPreviousInlineElement(): InlineElement;
private getPreviousNextInlineElement;
}
/**
* The class that helps search content around a position
*/
export class PositionContentSearcher {
private rootNode;
private position;
private text;
private word;
private inlineBefore;
private inlineAfter;
private traverser;
private traversingComplete;
private inlineElements;
private nearestNonTextInlineElement;
/**
* Create a new CursorData instance
* @param rootNode Root node of the whole scope
* @param position Start position
*/
constructor(rootNode: Node, position: NodePosition);
/**
* Get the word before position. The word is determined by scanning backwards till the first white space, the portion
* between position and the white space is the word before position
* @returns The word before position
*/
getWordBefore(): string;
/**
* Get the inline element before position
* @returns The inlineElement before position
*/
getInlineElementBefore(): InlineElement;
/**
* Get the inline element after position
* @returns The inline element after position
*/
getInlineElementAfter(): InlineElement;
/**
* Get X number of chars before position
* The actual returned chars may be less than what is requested.
* @param length The length of string user want to get, the string always ends at the position,
* so this length determins the start position of the string
* @returns The actual string we get as a sub string, or the whole string before position when
* there is not enough chars in the string
*/
getSubStringBefore(length: number): string;
/**
* Try to get a range matches the given text before the position
* @param text The text to match against
* @param exactMatch Whether it is an exact match
* @returns The range for the matched text, null if unable to find a match
*/
getRangeFromText(text: string, exactMatch: boolean): Range;
/**
* Get text section before position till stop condition is met.
* This offers consumers to retrieve text section by section
* The section essentially is just an inline element which has Container element
* so that the consumer can remember it for anchoring popup or verification purpose
* when position moves out of context etc.
* @param stopFunc The callback stop function
*/
forEachTextInlineElement(callback: (textInlineElement: InlineElement) => any): void;
/**
* Get first non textual inline element before position
* @returns First non textutal inline element before position or null if no such element exists
*/
getNearestNonTextInlineElement(): InlineElement;
/**
* Continue traversing backward till stop condition is met or begin of block is reached
*/
private traverse;
}
/**
* Get the inline element at a node
* @param rootNode The root node of current scope
* @param node The node to get InlineElement from
*/
export function getInlineElementAtNode(rootNode: Node, node: Node): InlineElement;
/**
* Get the inline element at a node
* @param parentBlock Parent BlockElement of this node
* @param node The node to get InlineElement from
*/
export function getInlineElementAtNode(parentBlock: BlockElement, node: Node): InlineElement;
/**
* This is an inline element representing an Html image
*/
export class ImageInlineElement extends NodeInlineElement {
constructor(containerNode: Node, parentBlock: BlockElement);
}
/**
* This is inline element presenting an html hyperlink
*/
export class LinkInlineElement extends NodeInlineElement {
constructor(containerNode: Node, parentBlock: BlockElement);
}
/**
* This presents an inline element that can be reprented by a single html node.
* This serves as base for most inline element as it contains most implentation
* of all operations that can happen on an inline element. Other sub inline elements mostly
* just identify themself for a certain type
*/
export class NodeInlineElement implements InlineElement {
private containerNode;
private parentBlock;
constructor(containerNode: Node, parentBlock: BlockElement);
/**
* The text content for this inline element
*/
getTextContent(): string;
/**
* Get the container node
*/
getContainerNode(): Node;
getParentBlock(): BlockElement;
/**
* Get the start position of the inline element
*/
getStartPosition(): NodePosition;
/**
* Get the end position of the inline element
*/
getEndPosition(): NodePosition;
/**
* Checks if this inline element is a textual inline element
*/
isTextualInlineElement(): boolean;
/**
* Checks if an inline element is after the current inline element
*/
isAfter(inlineElement: InlineElement): boolean;
/**
* Checks if the given position is contained in the inline element
*/
contains(pos: NodePosition): boolean;
/**
* Apply inline style to an inline element
*/
applyStyle(styler: (element: HTMLElement, isInnerNode?: boolean) => any): void;
}
/**
* This is a special version of inline element that identifies a section of an inline element
* We often have the need to cut an inline element in half and perform some operation only on half of an inline element
* i.e. users select only some text of a text node and apply format, in that case, format has to happen on partial of an inline element
* PartialInlineElement is implemented in a way that decorate another full inline element with its own override on methods like isAfter
* It also offers some special methods that others don't have, i.e. nextInlineElement etc.
*/
export class PartialInlineElement implements InlineElement {
private inlineElement;
private start?;
private end?;
constructor(inlineElement: InlineElement, start?: NodePosition, end?: NodePosition);
/**
* Get the full inline element that this partial inline decorates
*/
getDecoratedInline(): InlineElement;
/**
* Gets the container node
*/
getContainerNode(): Node;
/**
* Gets the parent block
*/
getParentBlock(): BlockElement;
/**
* Gets the text content
*/
getTextContent(): string;
/**
* Get start position of this inline element.
*/
getStartPosition(): NodePosition;
/**
* Get end position of this inline element.
*/
getEndPosition(): NodePosition;
/**
* Get next partial inline element if it is not at the end boundary yet
*/
get nextInlineElement(): PartialInlineElement;
/**
* Get previous partial inline element if it is not at the begin boundary yet
*/
get previousInlineElement(): PartialInlineElement;
/**
* Checks if it contains a position
*/
contains(pos: NodePosition): boolean;
/**
* Checks if this inline element is a textual inline element
*/
isTextualInlineElement(): boolean;
/**
* Check if this inline element is after the other inline element
*/
isAfter(inlineElement: InlineElement): boolean;
/**
* apply style
*/
applyStyle(styler: (element: HTMLElement, isInnerNode?: boolean) => any): void;
}
/**
* Apply style using a styler function to the given container node in the given range
* @param container The container node to apply style to
* @param styler The styler function
* @param from From position
* @param to To position
*/
export function applyTextStyle(container: Node, styler: (node: HTMLElement, isInnerNode?: boolean) => any, from?: NodePosition, to?: NodePosition): void;
/**
* Browser object contains browser and operating system informations of current environment
*/
export const Browser: BrowserInfo;
/**
* Get current browser information from user agent string
* @param userAgent The userAgent string of a browser
* @param appVersion The appVersion string of a browser
* @returns The BrowserInfo object calculated from the given userAgent and appVersion
*/
export function getBrowserInfo(userAgent: string, appVersion: string): BrowserInfo;
/**
* Apply format to an HTML element
* @param element The HTML element to apply format to
* @param format The format to apply
*/
export function applyFormat(element: HTMLElement, format: DefaultFormat, isDarkMode?: boolean): void;
/**
* Change tag of an HTML Element to a new one, and replace it from DOM tree
* @param element The element to change tag
* @param newTag New tag to change to
* @returns The new element with new tag
*/
export function changeElementTag<K extends keyof HTMLElementTagNameMap>(element: HTMLElement, newTag: K): HTMLElementTagNameMap[K];
/**
* Change tag of an HTML Element to a new one, and replace it from DOM tree
* @param element The element to change tag
* @param newTag New tag to change to
* @returns The new element with new tag
*/
export function changeElementTag(element: HTMLElement, newTag: string): HTMLElement;
/**
* Collapse nodes within the given start and end nodes to their common ascenstor node,
* split parent nodes if necessary
* @param root The root node of the scope
* @param start The start node
* @param end The end node
* @param canSplitParent True to allow split parent node there are nodes before start or after end under the same parent
* and the returned nodes will be all nodes from start trhough end after splitting
* False to disallow split parent
* @returns When cansplitParent is true, returns all node from start through end after splitting,
* otherwise just return start and end
*/
export function collapseNodes(root: Node, start: Node, end: Node, canSplitParent: boolean): Node[];
/**
* Test if a node contains another node
* @param container The container node
* @param contained The node to check if it is inside container
* @param treatSameNodeAsContain When container and contained are the same node,
* return true if this param is set to true, otherwise return false. Default value is false
* @returns True if contained is insied container, or they are the same node when treatSameNodeAsContain is true.
* Otherwise false.
*/
export function contains(container: Node, contained: Node, treatSameNodeAsContain?: boolean): boolean;
/**
* Test if a node contains a given range
* @param container The container node
* @param contained The range to check if it is inside container
* @returns True if contained is insied container, otherwise false
*/
export function contains(container: Node, contained: Range): boolean;
/**
* Extract a Clipboard event
* @param event The paste event
* @param callback Callback function when data is ready
* @param fallbackHtmlRetriever If direct HTML retriving is not support (e.g. Internet Explorer), as a fallback,
* using this helper function to retrieve HTML content
* @returns An object with the following properties:
* types: Available types from the clipboard event
* text: Plain text from the clipboard event
* image: Image file from the clipboard event
* html: Html string from the clipboard event. When set to null, it means there's no HTML found from the event.
* When set to undefined, it means can't retrieve HTML string, there may be HTML string but direct retrieving is
* not supported by browser.
*/
export function extractClipboardEvent(event: ClipboardEvent, callback: (items: ClipboardItems) => void): void;
/**
* Find closest element ancestor start from the given node which matches the given selector
* @param node Find ancestor start from this node
* @param root Root node where the search should stop at. The return value can never be this node
* @param selector The expected selector. If null, return the first HTML Element found from start node
* @returns An HTML element which matches the given selector. If the given start node matches the selector,
* returns the given node
*/
export function findClosestElementAncestor(node: Node, root?: Node, selector?: string): HTMLElement;
/**
* Creates an HTML node array from html
* @param html the html string to create HTML elements from
* @param ownerDocument Owner document of the result HTML elements
* @returns An HTML node array to represent the given html string
*/
export function fromHtml(html: string, ownerDocument: HTMLDocument): Node[];
/**
* Get computed styles of a node
* @param node The node to get computed styles from
* @param styleNames Names of style to get, can be a single name or an array.
* Default value is font-family, font-size, color, background-color
* @returns An array of the computed styles
*/
export function getComputedStyles(node: Node, styleNames?: string | string[]): string[];
/**
* A shortcut for getComputedStyles() when only one style is to be retrieved
* @param node The node to get style from
* @param styleName The style name
* @returns The style value
*/
export function getComputedStyle(node: Node, styleName: string): string;
/**
* Get Pendable Format State at cursor.
* @param document The HTML Document to get format state from
* @returns A PendableFormatState object which contains the values of pendable format states
*/
export function getPendableFormatState(document: Document): PendableFormatState;
/**
* A map from pendable format name to document command
*/
export const PendableFormatCommandMap: {
[key in PendableFormatNames]: DocumentCommand;
};
/**
* Names of Pendable formats
*/
export type PendableFormatNames = keyof PendableFormatState;
/**
* Get the html tag of a node, or empty if it is not an element
* @param node The node to get tag of
* @returns Tag name in upper case if the given node is an Element, or empty string otherwise
*/
export function getTagOfNode(node: Node): string;
/**
* Checks if the node is a block like element. Block like element are usually those P, DIV, LI, TD etc.
* @param node The node to check
* @returns True if the node is a block element, otherwise false
*/
export function isBlockElement(node: Node): node is HTMLElement;
/**
* Check if a given node has no visible content
* @param node The node to check
* @param trimContent Whether trim the text content so that spaces will be treated as empty.
* Default value is false
* @returns True if there isn't any visible element inside node, otherwise false
*/
export function isNodeEmpty(node: Node, trimContent?: boolean): boolean;
/**
* Check if the given element is using right-to-left layout
* @param element An HTML element to check
* @returns True if the given element is using right-to-left layout, otherwise false
*/
export function isRtl(element: HTMLElement): boolean;
/**
* Check if the given node is html void element. Void element cannot have childen
* @param node The node to check
*/
export function isVoidHtmlElement(node: Node): boolean;
/**
* Try to match a given string with link match rules, return matched link
* @param url Input url to match
* @param option Link match option, exact or partial. If it is exact match, we need
* to check the length of matched link and url
* @param rules Optional link match rules, if not passed, only the default link match
* rules will be applied
* @returns The matched link data, or null if no match found.
* The link data includes an original url and a normalized url
*/
export function matchLink(url: string): LinkData;
/**
* Adjust the given position and return a better position (if any) or the given position
* which will be the best one for inserting the given node.
* @param root Root node of the scope
* @param nodeToInsert The node about to be inserted
* @param position The original position to insert the node
*/
export function adjustNodeInsertPosition(root: HTMLElement, nodeToInsert: Node, position: NodePosition): NodePosition;
/**
* Query HTML elements in the container by a selector string
* @param container Container element to query from
* @param selector Selector string to query
* @param forEachCallback An optional callback to be invoked on each node in query result
* @param scope The scope of the query, default value is QueryScope.Body
* @param range The selection range to query with. This is required when scope is not Body
* @returns HTML Element array of the query result
*/
export function queryElements(container: HTMLElement, selector: string, forEachCallback?: (node: HTMLElement) => any, scope?: QueryScope, range?: Range): HTMLElement[];
/**
* Split parent node of the given node before/after the given node.
* When a parent node contains [A,B,C] and pass B as the given node,
* If split before, the new nodes will be [A][B,C] and returns [A];
* otherwise, it will be [A,B][C] and returns [C].
* @param node The node to split before/after
* @param splitBefore Whether split before or after
* @param removeEmptyNewNode If the new node is empty (even then only child is space or ZER_WIDTH_SPACE),
* we remove it. @default false
* @returns The new parent node
*/
export function splitParentNode(node: Node, splitBefore: boolean): Node;
/**
* Split parent node by a balanced node range
* @param nodes The nodes to split from. If only one node is passed, split it from all its siblings.
* If two or nodes are passed, will split before the first one and after the last one, all other nodes will be ignored
* @returns The parent node of the given node range if the given nodes are balanced, otherwise null
*/
export function splitBalancedNodeRange(nodes: Node | Node[]): HTMLElement;
/**
* Removes the node and keep all children in place, return the parentNode where the children are attached
* @param node the node to remove
*/
export function unwrap(node: Node): Node;
/**
* Wrap all the node with html and return the wrapped node, and put the wrapper node under the parent of the first node
* @param nodes The node or node array to wrap
* @param wrapper The wrapper HTML tag name
* @returns The wrapper element
*/
export function wrap<T extends keyof HTMLElementTagNameMap>(nodes: Node | Node[], wrapper?: T): HTMLElementTagNameMap[T];
/**
* Wrap all the node with html and return the wrapped node, and put the wrapper node under the parent of the first node
* @param nodes The node or node array to wrap
* @param wrapper The wrapper HTML string, default value is DIV
* @returns The wrapper element
*/
export function wrap(nodes: Node | Node[], wrapper?: string): HTMLElement;
/**
* Wrap all the node with html and return the wrapped node, and put the wrapper node under the parent of the first node
* @param nodes The node or node array to wrap
* @param wrapper The wrapper HTML element, default value is a new DIV element
* @returns The wrapper element
*/
export function wrap(nodes: Node | Node[], wrapper?: HTMLElement): HTMLElement;
/**
* This walks forwards DOM tree to get next meaningful node
* @param rootNode Root node to scope the leaf sibling node
* @param startNode current node to get sibling node from
* @param skipTags (Optional) tags that child elements will be skipped
*/
export function getNextLeafSibling(rootNode: Node, startNode: Node, skipTags?: string[]): Node;
/**
* This walks backwards DOM tree to get next meaningful node
* @param rootNode Root node to scope the leaf sibling node
* @param startNode current node to get sibling node from
* @param skipTags (Optional) tags that child elements will be skipped
*/
export function getPreviousLeafSibling(rootNode: Node, startNode: Node, skipTags?: string[]): Node;
/**
* Get the first meaningful leaf node
* @param rootNode Root node to get leaf node from
*/
export function getFirstLeafNode(rootNode: Node): Node;
/**
* Get the last meaningful leaf node
* @param rootNode Root node to get leaf node from
*/
export function getLastLeafNode(rootNode: Node): Node;
/**
* get block element's text content.
* @param rootNode Root node that the get the textContent of.
* @returns text content of given text content.
*/
export function getTextContent(rootNode: Node): string;
/**
* Split a text node into two parts by an offset number, and return one of them
* @param textNode The text node to split
* @param offset The offset number to split at
* @param returnFirstPart True to return the first part, then the passed in textNode will become the second part.
* Otherwise return the second part, and the passed in textNode will become the first part
*/
export function splitTextNode(textNode: Text, offset: number, returnFirstPart: boolean): Text;
/**
* Convert a named node map to an array
* @param collection The map to convert
*/
export function toArray(collection: NamedNodeMap): Attr[];
/**
* Convert a collection to an array
* @param collection The collection to convert
*/
export function toArray<T extends Node>(collection: NodeListOf<T>): T[];
/**
* Convert a collection to an array
* @param collection The collection to convert
*/
export function toArray<T extends Element>(collection: HTMLCollectionOf<T>): T[];
/**
* Convert an array to an array.
* This is to satisfy typescript compiler. For some cases the object can be a collection at runtime,
* but the declaration is an array. e.g. ClipboardData.types
* @param array The array to convert
*/
export function toArray<T>(array: readonly T[]): T[];
/**
* A virtual table class, represent an HTML table, by expand all merged cells to each separated cells
*/
export class VTable {
/**
* The HTML table object
*/
table: HTMLTableElement;
/**
* Virtual cells
*/
cells: VCell[][];
/**
* Current row index
*/
row: number;
/**
* Current column index
*/
col: number;
private trs;
/**
* Create a new instance of VTable object using HTML TABLE or TD node
* @param node The HTML Table or TD node
*/
constructor(node: HTMLTableElement | HTMLTableCellElement);
/**
* Write the virtual table back to DOM tree to represent the change of VTable
*/
writeBack(): void;
/**
* Apply the given table format to this virtual table
* @param format Table format to apply
*/
applyFormat(format: Partial<TableFormat>): void;
/**
* Edit table with given operation.
* @param operation Table operation
*/
edit(operation: TableOperation): void;
/**
* Loop each cell of current column and invoke a callback function
* @param callback The callback function to invoke
*/
forEachCellOfCurrentColumn(callback: (cell: VCell, row: VCell[], i: number) => any): void;
/**
* Loop each cell of current row and invoke a callback function
* @param callback The callback function to invoke
*/
forEachCellOfCurrentRow(callback: (cell: VCell, i: number) => any): void;
/**
* Get a table cell using its row and column index. This function will always return an object
* even if the given indexes don't exist in table.
* @param row The row index
* @param col The column index
*/
getCell(row: number, col: number): VCell;
/**
* Get current HTML table cell object. If the current table cell is a virtual expanded cell, return its root cell
*/
getCurrentTd(): HTMLTableCellElement;
private getTd;
private forEachCellOfColumn;
private forEachCellOfRow;
private recalcSpans;
private countSpanLeft;
private countSpanAbove;
}
/**
* Represent a virtual cell of a virtual table
*/
export interface VCell {
/**
* The table cell object. The value will be null if this is an expanded virtual cell
*/
td?: HTMLTableCellElement;
/**
* Whether this cell is spanned from left
*/
spanLeft?: boolean;
/**
* Whether this cell is spanned from above
*/
spanAbove?: boolean;
}
/**
* Represent a bullet or a numbering list
*
* @example
* A VList is a logical representation of list items, it contains an item array with node and list type stack.
* e.g. We have a list like this
* ```html
* <ol>
* <li>item 1</li>
* <li>item 2</li>
* <ul>
* <li>item 2.1</li>
* <li>item 2.2</li>
* <ul>
* </ol>
* ```
*
* A VList of this list will be like this:
* ```javascript
* {
* rootList: (OL node),
* items: [{
* node: (LI node with 'item 1'),
* listTypes: [null, OL],
* }, {
* node: (LI node with 'item 2'),
* listTypes: [null, OL],
* }, {
* node: (LI node with 'item 2.1),
* listTypes: [null, OL, UL],
* }, {
* node: (LI node with 'item 2.2'),
* listTypes: [null, OL, UL],
* }
* ]
* }
* ```
*
* When we want to outdent item 2.1, we just need to remove the last "UL" from listTypes of item 2.1, then
* the writeBack() function will handle everything related to DOM change
*/
export class VList {
private rootList;
private items;
/**
* Create a new instance of VList class
* @param rootList The root list element, can be either OL or UL tag
*/
constructor(rootList: HTMLOListElement | HTMLUListElement);
/**
* Check if this list contains the given node
* @param node The node to check
*/
contains(node: Node): boolean;
/**
* Get the first or last node of this list
* @param isLast true to get last node, false to get first node
*/
getFirstOrLastNode(isLast: boolean): Node;
/**
* Write the result back into DOM tree
* After that, this VList becomes unavailable because we set this.rootList to null
*/
writeBack(): void;
/**
* Set indentation of the given range of this list
* @param start Start position to operate from
* @param end End positon to operate to
* @param indentation Indent or outdent
*/
setIndentation(start: NodePosition, end: NodePosition, indentation: Indentation): void;
/**
* Change list type of the given range of this list.
* If some of the items are not real list item yet, this will make them to be list item with given type
* If all items in the given range are already in the type to change to, this becomes an outdent operation
* @param start Start position to operate from
* @param end End position to operate to
* @param targetType Target list type
*/
changeListType(start: NodePosition, end: NodePosition, targetType: ListType): void;
/**
* Append a new item to this VList
* @param node node of the item to append. If it is not wrapped with LI tag, it will be wrapped
* @param type Type of this list item, can be ListType.None
*/
appendItem(node: Node, type: ListType): void;
/**
* Merge the given VList into current VList.
* - All list items will be removed from the given VList and added into this list.
* - The root node of the given VList will be removed from DOM tree
* - If there are orphan items in the given VList, they will be merged into the last item
* of this list if any.
* @param list The vList to merge from
*/
mergeVList(list: VList): void;
private mergeOrphanNodesAfter;
private findListItems;
private populateItems;
}
/**
* @internal
* @param region The region to get VList from
* @param includeSiblingLists True to also try get lists before and after the selection and merge them together,
* false to only include the list for the selected blocks
* @param startNode (Optional) When specified, try get VList which will contain this node.
* If not specified, get VList from selection of this region
*/
export function createVListFromRegion(region: Region, includeSiblingLists?: boolean, startNode?: Node): VList;
/**
* Get regions impacted by the given range under the root node
* @param root Root node to get regions from
* @param range A selection range. Regions will be created acording to this range. Each region will be
* fully or partially covered by this range.
* @param type Type of region. Currently we only support TABLE region.
*/
export function getRegionsFromRange(root: HTMLElement, range: Range, type: RegionType): Region[];
/**
* Get all block elements covered by the selection under this region
*/
export function getSelectedBlockElementsInRegion(region: Region): BlockElement[];
/**
* Collapse nodes within this region to their common ascenstor node under this region
* @param region The region to collapse nodes in.
* @param nodes Nodes to collapse. All nodes not contained by the given region will be ignored.
*/
export function collapseNodesInRegion(region: Region, nodes: Node[]): Node[];
/**
* Check if a given node is contained by the given region
* @param region The region to check from
* @param node The node or block element to check
*/
export function isNodeInRegion(region: Region, node: Node): boolean;
/**
* Represent a position in DOM tree by the node and its offset index
*/
export class Position implements NodePosition {
private readonly isFromEndOfRange?;
readonly node: Node;
readonly element: HTMLElement;
readonly offset: number;
readonly isAtEnd: boolean;
/**
* Clone and validate a position from existing position.
* If the given position has invalid offset, this function will return a corrected value.
* @param position The original position to clone from
*/
constructor(position: NodePosition);
/**
* Create a Position from node and an offset number
* @param node The node of this position
* @param offset Offset of this position
* @param isFromEndOfRange Whether this position is created from end of a range. An position
* created from end of range has different behavior when normalize, it will use the child node
* before current position if any as a deeper level node and set isAtEnd to true.
*/
constructor(node: Node, offset: number, isFromEndOfRange?: boolean);
/**
* Create a Position from node and a type of position
* @param node The node of this position
* @param positionType Type of the postion, can be Begin, End, Before, After
*/
constructor(node: Node, positionType: PositionType);
/**
* Normalize this position to the leaf node, return the normalize result.
* If current position is already using leaf node, return this position object itself
*/
normalize(): NodePosition;
/**
* Check if this position is equal to the given position
* @param position The position to check
*/
equalTo(position: NodePosition): boolean;
/**
* Checks if this position is after the given position
*/
isAfter(position: NodePosition): boolean;
/**
* Move this position with offset, returns a new position with a valid offset in the same node
* @param offset Offset to move with
*/
move(offset: number): Position;
/**
* Get start position of the given Range
* @param range The range to get position from
*/
static getStart(range: Range): Position;
/**
* Get end position of the given Range
* @param range The range to get position from
*/
static getEnd(range: Range): Position;
}
/**
* Create a range around the given node(s)
* @param startNode The start node to create range from
* @param endNode The end node to create range from. If specified, the range will start before startNode and
* end after endNode, otherwise, the range will start before and end after the start node
* @returns A range start before the given node and end after the given node
*/
export function createRange(startNode: Node, endNode?: Node): Range;
/**
* Create a collapsed range at the given node and offset
* @param node The container node of the range
* @param offset The offset of the range, can be a number or value of PositionType
* @returns A range at the given node and offset
*/
export function createRange(node: Node, offset: number | PositionType): Range;
/**
* Create a range with the given start/end container node and offset
* @param startNode The start container node of the range
* @param startOffset The start offset of the range
* @param endNode The end container node of the range
* @param endOffset The end offset of the range
* @returns A range at the given start/end container node and offset
*/
export function createRange(startNode: Node, startOffset: number | PositionType, endNode: Node, endOffset: number | PositionType): Range;
/**
* Create a range under the given rootNode with start and end selection paths
* @param rootNode The root node that the selection paths start from
* @param startPath The selection path of the start position of the range
* @param endPath The selection path of the end position of the range
* @returns A range with the given start and end selection paths
*/
export function createRange(rootNode: Node, startPath: number[], endPath?: number[]): Range;
/**
* Create a range with the start and end position
* @param startPosition The start position of the range
* @param endPosition The end position of the range, if not specified, the range will be collapsed at start position
* @returns A range start at startPosition, end at endPosition, or startPosition when endPosition is not specified
*/
export function createRange(startPosition: NodePosition, endPosition?: NodePosition): Range;
/**
* @deprecated Use createRange instead
* Get range from the given selection path
* @param rootNode Root node of the selection path
* @param path The selection path which contains start and end position path
*/
export function getRangeFromSelectionPath(rootNode: HTMLElement, path: SelectionPath): Range;
/**
* Get bounding rect of this position
* @param position The positioin to get rect from
*/
export function getPositionRect(position: NodePosition): Rect;
/**
* Check if this position is at beginning of the given node.
* This will return true if all nodes between the beginning of target node and the position are empty.
* @param position The position to check
* @param targetNode The node to check
* @returns True if position is at beginning of the node, otherwise false
*/
export function isPositionAtBeginningOf(position: NodePosition, targetNode: Node): boolean;
/**
* Get path of the given selection range related to the given rootNode
* @param rootNode The root node where the path start from
* @param range The range of selection
*/
export function getSelectionPath(rootNode: HTMLElement, range: Range): SelectionPath;
/**
* Get inner Html of a root node with a selection path which can be used for restore selection.
* The result string can be used by setHtmlWithSelectionPath() to restore the HTML and selection.
* @param rootNode Root node to get inner Html from
* @param range The range of selection. If pass null, no selection path will be added
* @returns Inner HTML of the root node, followed by HTML comment contains selection path if the given range is valid
*/
export function getHtmlWithSelectionPath(rootNode: HTMLElement, range: Range): string;
/**
* Restore inner Html of a root element from given html string. If the string contains selection path,
* remove the selection path and return a range represented by the path
* @param root The root element
* @param html The html to restore
* @returns A selection range if the html contains a valid selection path, otherwise null
*/
export function setHtmlWithSelectionPath(rootNode: HTMLElement, html: string): Range;
/**
* Add a new snapshot to the given snapshots data structure
* @param snapshots The snapshots data structure to add new snapshot into
* @param snapshot The snapshot to add
*/
export function addSnapshot(snapshots: Snapshots, snapshot: string): void;
/**
* Check whether can move current snapshot with the given step
* @param snapshots The snapshots data structure to check
* @param step The step to check, can be positive, negative or 0
* @returns True if can move current snapshot with the given step, otherwise false
*/
export function canMoveCurrentSnapshot(snapshots: Snapshots, step: number): boolean;
/**
* Clear all snapshots after the current one
* @param snapshots The snapshots data structure to clear
*/
export function clearProceedingSnapshots(snapshots: Snapshots): void;
/**
* Move current snapshot with the given step if can move this step. Otherwise no action and return null
* @param snapshots The snapshots data structure to move
* @param step The step to move
* @returns If can move with the given step, returns the snapshot after move, otherwise null
*/
export function moveCurrentSnapsnot(snapshots: Snapshots, step: number): string;
/**
* Create initial snapshots
* @param maxSize max size of all snapshots
*/
export function createSnapshots(maxSize: number): Snapshots;
/**
* HTML sanitizer class provides two featuers:
* 1. Convert global CSS to inline CSS
* 2. Sanitize an HTML document, remove unnecessary/dangerous attribute/nodes
*/
export class HtmlSanitizer {
/**
* Convert global CSS to inline CSS if any
* @param html HTML source
* @param additionalStyleNodes (Optional) additional HTML STYLE elements used as global CSS
*/
static convertInlineCss(html: string, additionalStyleNodes?: HTMLStyleElement[]): string;
/**
* Sanitize HTML string, remove any unuseful HTML node/attribute/CSS.
* @param html HTML source string
* @param options Options used for this sanitizing process
*/
static sanitizeHtml(html: string, options?: SanitizeHtmlOptions): string;
private elementCallbacks;
private styleCallbacks;
private attributeCallbacks;
private allowedTags;
private allowedAttributes;
private allowedCssClassesRegex;
private defaultStyleValues;
private additionalGlobalStyleNodes;
private allowPreserveWhiteSpace;
/**
* Construct a new instance of HtmlSanitizer
* @param options Options for HtmlSanitizer
*/
constructor(options?: HtmlSanitizerOptions);
/**
* Sanitize HTML string
* This function will do the following work:
* 1. Convert global CSS into inline CSS
* 2. Remove dangerous HTML tags and attributes
* 3. Remove useless CSS properties
* @param html The input HTML
* @param convertInlineCssOnly Whether only convert inline css and skip html content sanitizing
* @param preserveFragmentOnly If set to true, only preserve the html content between <!--StartFragment--> and <!--Endfragment-->
* @param currentStyles Current inheritable CSS styles
*/
exec(html: string, convertCssOnly?: boolean, preserveFragmentOnly?: boolean, currentStyles?: StringMap): string;
/**
* Sanitize an HTML element, remove unnecessary or dangerous elements/attribute/CSS rules
* @param rootNode Root node to sanitize
* @param currentStyles Current CSS styles. Inheritable styles in the given node which has
* the same value with current styles will be ignored.
*/
sanitize(rootNode: HTMLElement, currentStyles?: StringMap): string;
/**
* Convert global CSS into inline CSS
* @param rootNode The HTML Document
*/
convertGlobalCssToInlineCss(rootNode: HTMLDocument): void;
private processNode;
private processCss;
private processAttributes;
private processCssClass;
private allowElement;
}
/**
* Build DOM tree from the given HTML string
* @param html Source HTML string
* @param preserveFragmentOnly If there is fragment markup (<!--StartFragment--> and <!--EndFragment-->),
* only preserve content between these markups
* @param fragmentHandler An optional callback to do customized fragment handling
*/
export function htmlToDom(html: string, preserveFragmentOnly: boolean, fragmentHandler?: (doc: HTMLDocument, sourceHtml: string) => void): HTMLDocument;
/**
* Split the HTML string using its fragment info
* @param html Source html string
* @returns [String within fragment, String before fragment, String after fragment]
*/
export function splitWithFragment(html: string): [string, string, string];
/**
* Get inheritable CSS style values from the given element
* @param element The element to get style from
*/
export function getInheritableStyles(element: HTMLElement): StringMap;
/**
* Check if the given object is DocumentFragment
* @param obj The object to check
*/
export function isDocumentFragment(obj: any): obj is DocumentFragment;
/**
* Check if the given object is HTMLElement
* @param obj The object to check
*/
export function isHTMLElement(obj: any): obj is HTMLElement;
/**
* Check if the given object is HTMLOListElement
* @param obj The object to check
*/
export function isHTMLOListElement(obj: any): obj is HTMLOListElement;
/**
* Check if the given object is HTMLTableCellElement
* @param obj The object to check
*/
export function isHTMLTableCellElement(obj: any): obj is HTMLTableCellElement;
/**
* Check if the given object is HTMLTableElement
* @param obj The object to check
*/
export function isHTMLTableElement(obj: any): obj is HTMLTableElement;
/**
* Check if the given object is Node
* @param obj The object to check
*/
export function isNode(obj: any): obj is Node;
/**
* Check if the given object is Range
* @param obj The object to check
*/
export function isRange(obj: any): obj is Range;
/**
* Check if the given object is instance of the target type
* @param obj Object to check
* @param typeName Target type name
*/
export function safeInstanceOf<T extends keyof TargetWindow>(obj: Node | Range, typeName: T): obj is TargetWindow[T];
/**
* ContentEditFeature interface that handles keyboard event
*/
export type ContentEditFeature = GenericContentEditFeature<PluginKeyboardEvent>;
/**
* Generic ContentEditFeature interface
*/
export interface GenericContentEditFeature<TEvent extends PluginEvent> {
keys: number[];
shouldHandleEvent: (event: TEvent, editor: Editor, ctrlOrMeta: boolean) => any;
handleEvent: (event: TEvent, editor: Editor) => ChangeSource | void;
allowFunctionKeys?: boolean;
}
/**
* Key numbers used for ContentEditFeature
*/
export const enum Keys {
NULL = 0,
BACKSPACE = 8,
TAB = 9,
ENTER = 13,
ESCAPE = 27,
SPACE = 32,
LEFT = 37,
UP = 38,
RIGHT = 39,
DOWN = 40,
DELETE = 46,
B = 66,
I = 73,
U = 85,
Y = 89,
Z = 90,
COMMA = 188,
PERIOD = 190,
FORWARDSLASH = 191,
Ctrl = 256,
Meta = 512,
Shift = 1024,
CONTENTCHANGED = 2048,
MOUSEDOWN = 4096
}
/**
* Custom data stored in editor
*/
export interface CustomData {
/**
* Value of this custom data
*/
value: any;
/**
* Optional disposer function of the custom data.
* When a valid value is set, it will be invoked when editor is disposing
*/
disposer?: (value: any) => void;
}
/**
* Define the type of a map from key to custom data
*/
export type CustomDataMap = {
[key: string]: CustomData;
};
/**
* Represents the core data structure of an editor
*/
export interface EditorCore {
/**
* HTML Document object of this editor
*/
readonly document: Document;
/**
* The content DIV element of this editor
*/
readonly contentDiv: HTMLDivElement;
/**
* The scroll container of editor, it can be the same with contentDiv,
* or some level of its scrollable parent.
*/
readonly scrollContainer: HTMLElement;
/**
* An array of editor plugins.
*/
readonly plugins: EditorPlugin[];
/**
* Plugins which will handle event via onPluginEvent() and/or willHandleEventExclusively()
*/
readonly eventHandlerPlugins: EditorPlugin[];
/**
* Default format of this editor
*/
defaultFormat: DefaultFormat;
/**
* Core plugin of this editor
*/
readonly corePlugins: CorePlugins;
/**
* Custom data of this editor
*/
readonly customData: CustomDataMap;
/**
* Core API map of this editor
*/
readonly api: CoreApiMap;
/**
* Core API map of this editor with default values (not overridable)
*/
readonly defaultApi: CoreApiMap;
/**
* The undo snapshot taken by addUndoSnapshot() before callback function is invoked.
*/
currentUndoSnapshot: string;
/**
* Cached selection range of this editor
*/
cachedSelectionRange: Range;
/**
* If the editor is in dark mode.
*/
inDarkMode: boolean;
/***
* The dark mode options, if set.
*/
darkModeOptions?: DarkModeOptions;
}
/**
* An interface for editor core plugins.
* These plugins are built-in and most of them are not able to be replaced
*/
export interface CorePlugins {
/**
* Edit plugin handles ContentEditFeatures
*/
readonly edit: EditPlugin;
/**
* Undo plugin provides the ability to undo/redo
*/
readonly undo: UndoService;
/**
* TypeInContainer plugin makes sure user is always type under a container element under editor DIV
*/
readonly typeInContainer: TypeInContainerPlugin;
/**
* MouseUp plugin helps generate MouseUp event even mouse is out of editor area
*/
readonly mouseUp: MouseUpPlugin;
/**
* DomEvent plugin helps handle additional DOM events such as IME composition, cut, drop.
*/
readonly domEvent: DOMEventPlugin;
/**
* FirefoxTypeAfterLink plugin helps workaround a Firefox bug to allow type outside a hyperlink
*/
readonly firefoxTypeAfterLink: FirefoxTypeAfterLink;
/**
* Copy plguin for handling dark mode copy.
*/
readonly copyPlugin: CopyPlugin;
}
export interface CoreApiMap {
/**
* Attach a DOM event to the editor content DIV
* @param core The EditorCore object
* @param eventName The DOM event name
* @param pluginEventType Optional event type. When specified, editor will trigger a plugin event with this name when the DOM event is triggered
* @param beforeDispatch Optional callback function to be invoked when the DOM event is triggered before trigger plugin event
*/
attachDomEvent: AttachDomEvent;
/**
* Call an editing callback with adding undo snapshots around, and trigger a ContentChanged event if change source is specified.
* Undo snapshot will not be added if this call is nested inside another editWithUndo() call.
* @param core The EditorCore object
* @param callback The editing callback, accepting current selection start and end position, returns an optional object used as the data field of ContentChangedEvent.
* @param changeSource The ChangeSource string of ContentChangedEvent. @default ChangeSource.Format. Set to null to avoid triggering ContentChangedEvent
*/
editWithUndo: EditWithUndo;
/**
* Focus to editor. If there is a cached selection range, use it as current selection
* @param core The EditorCore object
*/
focus: Focus;
/**
* Get custom data related with this editor
* @param core The EditorCore object
* @param key Key of the custom data
* @param getter Getter function. If custom data for the given key doesn't exist,
* call this function to get one and store it.
* @param disposer An optional disposer function to dispose this custom data when
* dispose editor.
*/
getCustomData: GetCustomData;
/**
* Get current or cached selection range
* @param core The EditorCore object
* @param tryGetFromCache Set to true to retrieve the selection range from cache if editor doesn't own the focus now
* @returns A Range object of the selection range
*/
getSelectionRange: GetSelectionRange;
/**
* Check if the editor has focus now
* @param core The EditorCore object
* @returns True if the editor has focus, otherwise false
*/
hasFocus: HasFocus;
/**
* Insert a DOM node into editor content
* @param core The EditorCore object. No op if null.
* @param option An insert option object to specify how to insert the node
*/
insertNode: InsertNode;
/**
* @deprecated Use SelectRange instead
* Select content
* @param core The EditorCore object
*/
select: Select;
/**
* Change the editor selection to the given range
* @param core The EditorCore object
* @param range The range to select
* @param skipSameRange When set to true, do nothing if the given range is the same with current selection
* in editor, otherwise it will always remove current selection ranage and set to the given one.
* This parameter is always treat as true in Edge to avoid some weird runtime exception.
*/
selectRange: SelectRange;
/**
* Trigger a plugin event
* @param core The EditorCore object
* @param pluginEvent The event object to trigger
* @param broadcast Set to true to skip the shouldHandleEventExclusively check
*/
triggerEvent: TriggerEvent;
}
/**
* Attach a DOM event to the editor content DIV
* @param core The EditorCore object
* @param eventName The DOM event name
* @param pluginEventType Optional event type. When specified, editor will trigger a plugin event with this name when the DOM event is triggered
* @param beforeDispatch Optional callback function to be invoked when the DOM event is triggered before trigger plugin event
*/
export type AttachDomEvent = (core: EditorCore, eventName: string, pluginEventType?: PluginEventType, beforeDispatch?: (event: UIEvent) => void) => () => void;
/**
* Call an editing callback with adding undo snapshots around, and trigger a ContentChanged event if change source is specified.
* Undo snapshot will not be added if this call is nested inside another editWithUndo() call.
* @param core The EditorCore object
* @param callback The editing callback, accepting current selection start and end position, returns an optional object used as the data field of ContentChangedEvent.
* @param changeSource The ChangeSource string of ContentChangedEvent. @default ChangeSource.Format. Set to null to avoid triggering ContentChangedEvent
*/
export type EditWithUndo = (core: EditorCore, callback: (start: NodePosition, end: NodePosition, snapshotBeforeCallback: string) => any, changeSource: ChangeSource | string) => void;
/**
* Focus to editor. If there is a cached selection range, use it as current selection
* @param core The EditorCore object
*/
export type Focus = (core: EditorCore) => void;
/**
* Get custom data related with this editor
* @param core The EditorCore object
* @param key Key of the custom data
* @param getter Getter function. If custom data for the given key doesn't exist,
* call this function to get one and store it if it is specified. Otherwise return undefined
* @param disposer An optional disposer function to dispose this custom data when
* dispose editor.
*/
export type GetCustomData = <T>(core: EditorCore, key: string, getter: () => T, disposer?: (value: T) => void) => T;
/**
* Get current or cached selection range
* @param core The EditorCore object
* @param tryGetFromCache Set to true to retrieve the selection range from cache if editor doesn't own the focus now
* @returns A Range object of the selection range
*/
export type GetSelectionRange = (core: EditorCore, tryGetFromCache: boolean) => Range;
/**
* Check if the editor has focus now
* @param core The EditorCore object
* @returns True if the editor has focus, otherwise false
*/
export type HasFocus = (core: EditorCore) => boolean;
/**
* Insert a DOM node into editor content
* @param core The EditorCore object. No op if null.
* @param option An insert option object to specify how to insert the node
*/
export type InsertNode = (core: EditorCore, node: Node, option: InsertOption) => boolean;
/**
* @deprecated Use SelectRange instead
* Select content
* @param core The EditorCore object
*/
export type Select = (core: EditorCore, arg1: any, arg2?: any, arg3?: any, arg4?: any) => boolean;
/**
* Change the editor selection to the given range
* @param core The EditorCore object
* @param range The range to select
* @param skipSameRange When set to true, do nothing if the given range is the same with current selection
* in editor, otherwise it will always remove current selection ranage and set to the given one.
* This parameter is always treat as true in Edge to avoid some weird runtime exception.
*/
export type SelectRange = (core: EditorCore, range: Range, skipSameRange?: boolean) => boolean;
/**
* Trigger a plugin event
* @param core The EditorCore object
* @param pluginEvent The event object to trigger
* @param broadcast Set to true to skip the shouldHandleEventExclusively check
*/
export type TriggerEvent = (core: EditorCore, pluginEvent: PluginEvent, broadcast: boolean) => void;
/**
* The options to specify parameters customizing an editor, used by ctor of Editor class
*/
export interface EditorOptions {
/**
* List of plugins.
* The order of plugins here determines in what order each event will be dispatched.
* Plugins not appear in t his list will not be added to editor, including bulit-in plugins.
* Default value is empty array.
*/
plugins?: EditorPlugin[];
/**
* Default format of editor content. This will be applied to empty content.
* If there is already content inside editor, format of existing content will not be changed.
* Default value is the computed style of editor content DIV
*/
defaultFormat?: DefaultFormat;
/**
* Undo service object. Use this parameter to customize the undo service.
* Default value is a new instance of Undo object
*/
undo?: UndoService;
/**
* Initial HTML content
* Default value is whatever already inside the editor content DIV
*/
initialContent?: string;
/**
* Whether auto restore previous selection when focus to editor
* Default value is false
*/
disableRestoreSelectionOnFocus?: boolean;
/**
* Whether skip setting contenteditable attribute to content DIV
* Default value is false
*/
omitContentEditableAttributeChanges?: boolean;
/**
* A function map to override default core API implementation
* Default value is null
*/
coreApiOverride?: Partial<CoreApiMap>;
/**
* Additional content edit features
*/
additionalEditFeatures?: GenericContentEditFeature<PluginEvent>[];
/**
* If the editor is currently in dark mode
*/
inDarkMode?: boolean;
/**
* Dark mode options for default format and paste handler
*/
darkModeOptions?: DarkModeOptions;
/**
* Initial custom data.
* Use this option to set custom data before any plugin is initialized,
* so that plugins can access the custom data safely.
* The value of this map is the value of each custom data. No disposer function to specify here.
* Because when set custom data via this way, it means the custom data value is created before editor,
* so editor shouldn't control the lifecycle of these objects, and caller need to manage its lifecycle.
*/
customData?: {
[key: string]: any;
};
/**
* The scroll container to get scroll event from.
* By default, the scroll container will be the same with editor content DIV
*/
scrollContainer?: HTMLElement;
/**
* Whether enable experiment features
*/
enableExperimentFeatures?: boolean;
}
/**
* Interface of an editor plugin
*/
export interface EditorPlugin {
/**
* Get a friendly name of this plugin
*/
getName: () => string;
/**
* The first method that editor will call to a plugin when editor is initializing.
* It will pass in the editor instance, plugin should take this chance to save the
* editor reference so that it can call to any editor method or format API later.
* @param editor The editor object
*/
initialize: (editor: Editor) => void;
/**
* The last method that editor will call to a plugin before it is disposed.
* Plugin can take this chance to clear the reference to editor. After this method is
* called, plugin should not call to any editor method since it will result in error.
*/
dispose: () => void;
/**
* Check if the plugin should handle the given event exclusively.
* Handle an event exclusively means other plugin will not receive this event in
* onPluginEvent method.
* If two plugins will return true in willHandleEventExclusively() for the same event,
* the final result depends on the order of the plugins are added into editor
* @param event The event to check:
*/
willHandleEventExclusively?: (event: PluginEvent) => boolean;
/**
* Core method for a plugin. Once an event happens in editor, editor will call this
* method of each plugin to handle the event as long as the event is not handled
* exclusively by another plugin.
* @param event The event to handle:
*/
onPluginEvent?: (event: PluginEvent) => void;
}
/**
* Defines replaceable undo service for editor
*/
export interface UndoService extends EditorPlugin {
/**
* Undo last change if any
*/
undo: () => void;
/**
* Redo next change if any
*/
redo: () => void;
/**
* Add an undo snapshot for current content inside editor
* This method will not trigger ExtractContent event, so any temporary content will be
* added into undo snapshot
*/
addUndoSnapshot: () => string;
/**
* Whether there is snapshot for undo
*/
canUndo: () => boolean;
/**
* Whether there is snapshot for redo
*/
canRedo: () => boolean;
/**
* Clear all existing undo snapshots
*/
clear: () => void;
}
/**
* Represent an interface to provide functionalities for Undo Snapshots
*/
export interface UndoSnapshotsService {
/**
* Check whether can move current undo snapshot with the given step
* @param step The step to check, can be positive, negative or 0
* @returns True if can move current snapshot with the given step, otherwise false
*/
canMove(step: number): boolean;
/**
* Move current snapshot with the given step if can move this step. Otherwise no action and return null
* @param step The step to move
* @returns If can move with the given step, returns the snapshot after move, otherwise null
*/
move(step: number): string;
/**
* Add a new undo snapshot
* @param snapshot The snapshot to add
*/
addSnapshot(snapshot: string): void;
/**
* Clear all undo snapshots after the current one
*/
clearRedo(): void;
}
/**
* RoosterJs core editor class
*/
export class Editor {
private core;
private eventDisposers;
private contenteditableChanged;
private enableExperimentFeatures;
/**
* Creates an instance of Editor
* @param contentDiv The DIV HTML element which will be the container element of editor
* @param options An optional options object to customize the editor
*/
constructor(contentDiv: HTMLDivElement, options?: EditorOptions);
/**
* Dispose this editor, dispose all plugins and custom data
*/
dispose(): void;
/**
* Get whether this editor is disposed
* @returns True if editor is disposed, otherwise false
*/
isDisposed(): boolean;
/**
* Insert node into editor
* @param node The node to insert
* @param option Insert options. Default value is:
* position: ContentPosition.SelectionStart
* updateCursor: true
* replaceSelection: true
* insertOnNewLine: false
* @returns true if node is inserted. Otherwise false
*/
insertNode(node: Node, option?: InsertOption): boolean;
/**
* Delete a node from editor content
* @param node The node to delete
* @returns true if node is deleted. Otherwise false
*/
deleteNode(node: Node): boolean;
/**
* Replace a node in editor content with another node
* @param existingNode The existing node to be replaced
* @param new node to replace to
* @returns true if node is replaced. Otherwise false
*/
replaceNode(existingNode: Node, toNode: Node): boolean;
/**
* Get InlineElement at given node
* @param node The node to create InlineElement
* @returns The InlineElement result
*/
getInlineElementAtNode(node: Node): InlineElement;
/**
* Get BlockElement at given node
* @param node The node to create InlineElement
* @returns The BlockElement result
*/
getBlockElementAtNode(node: Node): BlockElement;
/**
* Check if the node falls in the editor content
* @param node The node to check
* @returns True if the given node is in editor content, otherwise false
*/
contains(node: Node): boolean;
/**
* Check if the range falls in the editor content
* @param range The range to check
* @returns True if the given range is in editor content, otherwise false
*/
contains(range: Range): boolean;
/**
* Query HTML elements in editor by tag name
* @param tag Tag name of the element to query
* @param forEachCallback An optional callback to be invoked on each element in query result
* @returns HTML Element array of the query result
*/
queryElements<T extends keyof HTMLElementTagNameMap>(tag: T, forEachCallback?: (node: HTMLElementTagNameMap[T]) => any): HTMLElementTagNameMap[T][];
/**
* Query HTML elements in editor by a selector string
* @param selector Selector string to query
* @param forEachCallback An optional callback to be invoked on each node in query result
* @returns HTML Element array of the query result
*/
queryElements<T extends HTMLElement = HTMLElement>(selector: string, forEachCallback?: (node: T) => any): T[];
/**
* Query HTML elements with the given scope by tag name
* @param tag Tag name of the element to query
* @param scope The scope of the query, default value is QueryScope.Body
* @param forEachCallback An optional callback to be invoked on each element in query result
* @returns HTML Element list of the query result
*/
queryElements<T extends keyof HTMLElementTagNameMap>(tag: T, scope: QueryScope, forEachCallback?: (node: HTMLElementTagNameMap[T]) => any): HTMLElementTagNameMap[T][];
/**
* Query HTML elements with the given scope by a selector string
* @param selector Selector string to query
* @param scope The scope of the query, default value is QueryScope.Body
* @param forEachCallback An optional callback to be invoked on each element in query result
* @returns HTML Element array of the query result
*/
queryElements<T extends HTMLElement = HTMLElement>(selector: string, scope: QueryScope, forEachCallback?: (node: T) => any): T[];
/**
* Collapse nodes within the given start and end nodes to their common ascenstor node,
* split parent nodes if necessary
* @param start The start node
* @param end The end node
* @param canSplitParent True to allow split parent node there are nodes before start or after end under the same parent
* and the returned nodes will be all nodes from start trhough end after splitting
* False to disallow split parent
* @returns When cansplitParent is true, returns all node from start through end after splitting,
* otherwise just return start and end
*/
collapseNodes(start: Node, end: Node, canSplitParent: boolean): Node[];
/**
* Check whether the editor contains any visible content
* @param trim Whether trime the content string before check. Default is false
* @returns True if there's no visible content, otherwise false
*/
isEmpty(trim?: boolean): boolean;
/**
* Get current editor content as HTML string
* @param triggerExtractContentEvent Whether trigger ExtractContent event to all plugins
* before return. Use this parameter to remove any temporary content added by plugins.
* @param includeSelectionMarker Set to true if need include selection marker inside the content.
* When restore this content, editor will set the selection to the position marked by these markers.
* This parameter will be ignored when triggerExtractContentEvent is set to true
* @returns HTML string representing current editor content
*/
getContent(triggerExtractContentEvent?: boolean, includeSelectionMarker?: boolean): string;
/**
* Get plain text content inside editor
* @returns The text content inside editor
*/
getTextContent(): string;
/**
* Set HTML content to this editor. All existing content will be replaced. A ContentChanged event will be triggered
* @param content HTML content to set in
* @param triggerContentChangedEvent True to trigger a ContentChanged event. Default value is true
*/
setContent(content: string, triggerContentChangedEvent?: boolean): void;
/**
* Insert HTML content into editor
* @param HTML content to insert
* @param option Insert options. Default value is:
* position: ContentPosition.SelectionStart
* updateCursor: true
* replaceSelection: true
* insertOnNewLine: false
*/
insertContent(content: string, option?: InsertOption): void;
/**
* Get current selection range from Editor.
* It does a live pull on the selection, if nothing retrieved, return whatever we have in cache.
* @returns current selection range, or null if editor never got focus before
*/
getSelectionRange(): Range;
/**
* Get current selection in a serializable format
* It does a live pull on the selection, if nothing retrieved, return whatever we have in cache.
* @returns current selection path, or null if editor never got focus before
*/
getSelectionPath(): SelectionPath;
/**
* Check if focus is in editor now
* @returns true if focus is in editor, otherwise false
*/
hasFocus(): boolean;
/**
* Focus to this editor, the selection was restored to where it was before, no unexpected scroll.
*/
focus(): void;
/**
* Select content by range
* @param range The range to select
* @returns True if content is selected, otherwise false
*/
select(range: Range): boolean;
/**
* Select content by Position and collapse to this position
* @param position The position to select
* @returns True if content is selected, otherwise false
*/
select(position: NodePosition): boolean;
/**
* Select content by a start and end position
* @param start The start position to select
* @param end The end position to select, if this is the same with start, the selection will be collapsed
* @returns True if content is selected, otherwise false
*/
select(start: NodePosition, end: NodePosition): boolean;
/**
* Select content by node
* @param node The node to select
* @returns True if content is selected, otherwise false
*/
select(node: Node): boolean;
/**
* Select content by node and offset, and collapse to this position
* @param node The node to select
* @param offset The offset of node to select, can be a number or value of PositionType
* @returns True if content is selected, otherwise false
*/
select(node: Node, offset: number | PositionType): boolean;
/**
* Select content by start and end nodes and offsets
* @param startNode The node to select start from
* @param startOffset The offset to select start from
* @param endNode The node to select end to
* @param endOffset The offset to select end to
* @returns True if content is selected, otherwise false
*/
select(startNode: Node, startOffset: number | PositionType, endNode: Node, endOffset: number | PositionType): boolean;
/**
* Select content by selection path
* @param path A selection path object
* @returns True if content is selected, otherwise false
*/
select(path: SelectionPath): boolean;
/**
* Get current selection
* @return current selection object
*/
getSelection(): Selection;
/**
* Save the current selection in editor so that when focus again, the selection can be restored
*/
saveSelectionRange(): void;
/**
* Restore the saved selection range and clear it
*/
restoreSavedRange(): void;
/**
* Get current focused position. Return null if editor doesn't have focus at this time.
*/
getFocusedPosition(): NodePosition;
/**
* Get a rect representing the location of the cursor.
* @returns a Rect object representing cursor location
*/
getCursorRect(): Rect;
/**
* Get an HTML element from current cursor position.
* When expectedTags is not specified, return value is the current node (if it is HTML element)
* or its parent node (if current node is a Text node).
* When expectedTags is specified, return value is the first anscestor of current node which has
* one of the expected tags.
* If no element found within editor by the given tag, return null.
* @param selector Optional, an HTML selector to find HTML element with.
* @param startFrom Start search from this node. If not specified, start from current focused position
*/
getElementAtCursor(selector?: string, startFrom?: Node): HTMLElement;
/**
* Check if this position is at beginning of the editor.
* This will return true if all nodes between the beginning of target node and the position are empty.
* @param position The position to check
* @returns True if position is at beginning of the editor, otherwise false
*/
isPositionAtBeginning(position: NodePosition): boolean;
/**
* Get impacted regions from selection
*/
getSelectedRegions(type?: RegionType): Region[];
/**
* Add a custom DOM event handler to handle events not handled by roosterjs.
* Caller need to take the responsibility to dispose the handler properly
* @param eventName DOM event name to handle
* @param handler Handler callback
* @returns A dispose function. Call the function to dispose this event handler
*/
addDomEventHandler(eventName: string, handler: (event: UIEvent) => void): () => void;
/**
* Add a bunch of custom DOM event handler to handle events not handled by roosterjs.
* Caller need to take the responsibility to dispose the handler properly
* @param handlerMap A event name => event handler map
* @returns A dispose function. Call the function to dispose all event handlers added by this function
*/
addDomEventHandler(handlerMap: {
[eventName: string]: (event: UIEvent) => void;
}): () => void;
/**
* Trigger an event to be dispatched to all plugins
* @param eventType Type of the event
* @param data data of the event with given type, this is the rest part of PluginEvent with the given type
* @param broadcast indicates if the event needs to be dispatched to all plugins
* True means to all, false means to allow exclusive handling from one plugin unless no one wants that
* @returns the event object which is really passed into plugins. Some plugin may modify the event object so
* the result of this function provides a chance to read the modified result
*/
triggerPluginEvent<T extends PluginEventType>(eventType: T, data: PluginEventData<T>, broadcast?: boolean): PluginEventFromType<T>;
/**
* @deprecated Use triggerPluginEvent instead
*/
triggerEvent(pluginEvent: PluginEvent, broadcast?: boolean): void;
/**
* Trigger a ContentChangedEvent
* @param source Source of this event, by default is 'SetContent'
* @param data additional data for this event
*/
triggerContentChangedEvent(source?: ChangeSource | string, data?: any): void;
/**
* Undo last edit operation
*/
undo(): void;
/**
* Redo next edit operation
*/
redo(): void;
/**
* Add undo snapshot, and execute a format callback function, then add another undo snapshot, then trigger
* ContentChangedEvent with given change source.
* If this function is called nested, undo snapshot will only be added in the outside one
* @param callback The callback function to perform formatting, returns a data object which will be used as
* the data field in ContentChangedEvent if changeSource is not null.
* @param changeSource The change source to use when fire ContentChangedEvent. When the value is not null,
* a ContentChangedEvent will be fired with change source equal to this value
*/
addUndoSnapshot(callback?: (start: NodePosition, end: NodePosition, snapshotBeforeCallback: string) => any, changeSource?: ChangeSource | string): void;
/**
* Perform an auto complete action in the callback, save a snapsnot of content before the action,
* and trigger ContentChangedEvent with the change source if specified
* @param callback The auto complete callback, return value will be used as data field of ContentChangedEvent
* @param changeSource Chagne source of ContentChangedEvent. If not passed, no ContentChangedEvent will be triggered
*/
performAutoComplete(callback: () => any, changeSource?: ChangeSource | string): void;
/**
* Whether there is an available undo snapshot
*/
canUndo(): boolean;
/**
* Whether there is an available redo snapshot
*/
canRedo(): boolean;
/**
* Get document which contains this editor
* @returns The HTML document which contains this editor
*/
getDocument(): Document;
/**
* Get the scroll container of the editor
*/
getScrollContainer(): HTMLElement;
/**
* Get custom data related to this editor
* @param key Key of the custom data
* @param getter Getter function. If custom data for the given key doesn't exist,
* call this function to get one and store it if it is specified. Otherwise return undefined
* @param disposer An optional disposer function to dispose this custom data when
* dispose editor.
*/
getCustomData<T>(key: string, getter?: () => T, disposer?: (value: T) => void): T;
/**
* Check if editor is in IME input sequence
* @returns True if editor is in IME input sequence, otherwise false
*/
isInIME(): boolean;
/**
* Get default format of this editor
* @returns Default format object of this editor
*/
getDefaultFormat(): DefaultFormat;
/**
* Get a content traverser for the whole editor
* @param startNode The node to start from. If not passed, it will start from the beginning of the body
*/
getBodyTraverser(startNode?: Node): ContentTraverser;
/**
* Get a content traverser for current selection
*/
getSelectionTraverser(): ContentTraverser;
/**
* Get a content traverser for current block element start from specified position
* @param startFrom Start position of the traverser. Default value is ContentPosition.SelectionStart
*/
getBlockTraverser(startFrom?: ContentPosition): ContentTraverser;
/**
* Get a text traverser of current selection
*/
getContentSearcherOfCursor(): PositionContentSearcher;
/**
* Run a callback function asynchronously
* @param callback The callback function to run
*/
runAsync(callback: () => void): void;
/**
* Set DOM attribute of editor content DIV
* @param name Name of the attribute
* @param value Value of the attribute
*/
setEditorDomAttribute(name: string, value: string): void;
/**
* get DOM attribute of editor content DIV
* @param name Name of the attribute
*/
getEditorDomAttribute(name: string): string;
/**
* Add a Content Edit feature. This is mostly called from ContentEdit plugin
* @param feature The feature to add
*/
addContentEditFeature(feature: GenericContentEditFeature<PluginEvent>): void;
/**
* Set the dark mode state and transforms the content to match the new state.
* @param nextDarkMode The next status of dark mode. True if the editor should be in dark mode, false if not.
*/
setDarkModeState(nextDarkMode?: boolean): void;
/**
* Check if the editor is in dark mode
* @returns True if the editor is in dark mode, otherwise false
*/
isDarkMode(): boolean;
/**
* Returns the dark mode options set on the editor
* @returns A DarkModeOptions object
*/
getDarkModeOptions(): DarkModeOptions;
/**
* Whether experiment features can be used
*/
useExperimentFeatures(): boolean;
}
/**
* Provides snapshot based undo service for Editor
*/
export class Undo implements UndoService {
private preserveSnapshots?;
private maxBufferSize;
private editor;
private isRestoring;
private hasNewContent;
private lastKeyPress;
protected undoSnapshots: UndoSnapshotsService;
/**
* Create an instance of Undo
* @param preserveSnapshots True to preserve the snapshots after dispose, this allows
* this object to be reused when editor is disposed and created again
* @param maxBufferSize The max buffer size for snapshots. Default value is 10MB
*/
constructor(preserveSnapshots?: boolean, maxBufferSize?: number);
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
/**
* Clear all existing undo snapshots
*/
clear(): void;
/**
* Restore an undo snapshot to editor
*/
undo(): void;
/**
* Restore a redo snapshot to editor
*/
redo(): void;
/**
* Whether there is a snapshot for undo
*/
canUndo(): boolean;
/**
* Whether there is a snapshot for redo
*/
canRedo(): boolean;
/**
* Add an undo snapshot
*/
addUndoSnapshot(): string;
protected getSnapshotsManager(): UndoSnapshotsService;
private restoreSnapshot;
private onKeyDown;
private onKeyPress;
private clearRedoForInput;
}
/**
* Edit Component helps handle Content edit features
*/
export class EditPlugin implements EditorPlugin {
private editor;
private featureMap;
private autoCompleteSnapshot;
private autoCompleteChangeSource;
getName(): string;
initialize(editor: Editor): void;
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
/**
* Add a Content Edit feature
* @param feature The feature to add
*/
addFeature(feature: GenericContentEditFeature<PluginEvent>): void;
/**
* Perform an auto complete action in the callback, save a snapsnot of content before the action,
* and trigger ContentChangedEvent with the change source if specified
* @param callback The auto complete callback, return value will be used as data field of ContentChangedEvent
* @param changeSource Chagne source of ContentChangedEvent. If not passed, no ContentChangedEvent will be triggered
*/
performAutoComplete(callback: () => any, changeSource?: ChangeSource | string): void;
private findFeature;
}
/**
* MouseUp Component helps handle mouse up event
* this can trigger mouse up event after mousedown happens in editor
* even mouse up is happening outside editor
*/
export class MouseUpPlugin implements EditorPlugin {
private mouseUpEventListerAdded;
private editor;
getName(): string;
initialize(editor: Editor): void;
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
private removeMouseUpEventListener;
private onMouseUp;
}
/**
* DOMEventPlugin handles customized DOM events, including:
* 1. IME state management
* 2. Selection management
* 3. Cut and Drop management
* 4. Pending format state management
* 5. Scroll container and scroll event management
*/
export class DOMEventPlugin implements EditorPlugin {
private disableRestoreSelectionOnFocus;
private editor;
private inIme;
private disposer;
private cachedPosition;
private cachedFormatState;
constructor(disableRestoreSelectionOnFocus: boolean);
getName(): string;
initialize(editor: Editor): void;
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
/**
* Restore cached pending format state (if exist) to current selection
*/
restorePendingFormatState(): void;
/**
* Check if editor is in IME input sequence
* @returns True if editor is in IME input sequence, otherwise false
*/
isInIME(): boolean;
private onNativeEvent;
private onFocus;
private onBlur;
private onScroll;
private clear;
private getCurrentPosition;
}
/**
* Typing Component helps to ensure typing is always happening under a DOM container
*/
export class TypeInContainerPlugin implements EditorPlugin {
private editor;
getName(): string;
initialize(editor: Editor): void;
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
/**
* Ensure we are typing in an HTML Element inside editor, and apply default format if current block is empty
* @param node Current node
* @param event (optional) The keyboard event that we are ensuring is typing in an element.
* @returns A new position to select
*/
ensureTypeInElement(position: NodePosition, event?: PluginKeyboardEvent): NodePosition;
private onKeyPress;
/**
* When typing goes directly under content div, many things can go wrong
* We fix it by wrapping it with a div and reposition cursor within the div
*/
private tryNormalizeTyping;
private wasNodeJustCreatedByKeyboardEvent;
}
/**
* FirefoxTypeAfterLink Component helps handle typing event when cursor is right after a link.
* When typing/pasting after a link, browser may put the new charactor inside link.
* This plugin overrides this behavior to always insert outside of link.
*
* TODO: Rename this file in next major release since it is not only applied to Firefox now
*/
export class FirefoxTypeAfterLink implements EditorPlugin {
private editor;
getName(): string;
initialize(editor: Editor): void;
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
}
/**
* Copy plugin, hijacks copy events to normalize the content to the clipboard.
*/
export class CopyPlugin implements EditorPlugin {
private editor;
private eventDisposer;
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
/**
* Handle plugin events
* @param event The event to handle
*/
onPluginEvent(event: PluginEvent): void;
private onExtract;
}
/**
* Gets the cached event data by cache key from event object if there is already one.
* Otherwise, call getter function to create one, and cache it.
* @param event The event object
* @param key Cache key string, need to be unique
* @param getter Getter function to get the object when it is not in cache yet
*/
export function cacheGetEventData<T>(event: PluginEvent, key: string, getter: () => T): T;
/**
* Clear a cached object by its key from an event object
* @param event The event object
* @param key The cache key
*/
export function clearEventDataCache(event: PluginEvent, key: string): void;
/**
* Try get existing PositionContentSearcher from an event. If there isn't one, create a new one from editor.
* @param event The plugin event, it stores the event cached data for looking up.
* If passed as null, we will create a new PositionContentSearcher
* @param editor The editor instance
* @returns The PositionContentSearcher object
*/
export function cacheGetContentSearcher(event: PluginEvent, editor: Editor): PositionContentSearcher;
/**
* Clear the PositionContentSearcher in a plugin event.
* This is called when the content is changed
* @param event The plugin event
*/
export function clearContentSearcherCache(event: PluginEvent): void;
/**
* Get an HTML element at cursor from event cache if it exists.
* If an selector is specified, return the nearest ancestor of current node
* which matches the selector, or null if no match found in editor.
* @param editor The editor instance
* @param event Event object to get cached object from
* @param selector The expected selector. If null, return the element at cursor
* @returns The element at cursor or the nearest ancestor with the tag name is specified
*/
export function cacheGetElementAtCursor(editor: Editor, event: PluginEvent, selector: string): HTMLElement;
/**
* Returns true when the event was fired from a modifier key, otherwise false
* @param event The keyboard event object
*/
export function isModifierKey(event: KeyboardEvent): boolean;
/**
* Returns true when the event was fired from a key that produces a character value, otherwise false
* This detection is not 100% accurate. event.key is not fully supported by all browsers, and in some browsers (e.g. IE),
* event.key is longer than 1 for num pad input. But here we just want to improve performance as much as possible.
* So if we missed some case here it is still acceptable.
* @param event The keyboard event object
*/
export function isCharacterValue(event: KeyboardEvent): boolean;
/**
* Check if Ctrl key (Windows) or Meta key (Mac) is pressed for the given Event
* @param event A Keyboard event or Mouse event object
* @returns True if Ctrl key is pressed on Windows or Meta key is pressed on Mac
*/
export const isCtrlOrMetaPressed: (event: KeyboardEvent | MouseEvent) => boolean;
/**
* Increase or decrease font size in selection
* @param editor The editor instance
* @param change Whether increase or decrease font size
* @param fontSizes A sorted font size array, in pt. Default value is FONT_SIZES
*/
export function changeFontSize(editor: Editor, change: FontSizeChange, fontSizes?: number[]): void;
/**
* Default font size sequence, in pt. Suggest editor UI use this sequence as your font size list,
* So that when increase/decrease font size, the font size can match the sequence of your font size picker
*/
export const FONT_SIZES: number[];
/**
* Clear all formats of selected blocks.
* When selection is collapsed, only clear format of current block.
* @param editor The editor instance
* @param tagsToUnwrap Optional. A string array contains HTML tags in upper case which we will unwrap when clear format
* @param tagsToStopUnwrap Optional. A string array contains HTML tags in upper case which we will stop unwrap if these tags are hit
*/
export function clearBlockFormat(editor: Editor, tagsToUnwrap?: string[], tagsToStopUnwrap?: string[], attributesToPreserve?: string[]): void;
export const TAGS_TO_UNWRAP: string[];
export const TAGS_TO_STOP_UNWRAP: string[];
export const ATTRIBUTES_TO_PRESERVE: string[];
/**
* Clear the format in current selection, after cleaning, the format will be
* changed to default format. The format that get cleaned include B/I/U/font name/
* font size/text color/background color/align left/align right/align center/superscript/subscript
* @param editor The editor instance
*/
export function clearFormat(editor: Editor): void;
/**
* Insert a hyperlink at cursor.
* When there is a selection, hyperlink will be applied to the selection,
* otherwise a hyperlink will be inserted to the cursor position.
* @param editor Editor object
* @param link Link address, can be http(s), mailto, notes, file, unc, ftp, news, telnet, gopher, wais.
* When protocol is not specified, a best matched protocol will be predicted.
* @param altText Optional alt text of the link, will be shown when hover on the link
* @param displayText Optional display text for the link.
* If specified, the display text of link will be replaced with this text.
* If not specified and there wasn't a link, the link url will be used as display text.
*/
export function createLink(editor: Editor, link: string, altText?: string, displayText?: string): void;
/**
* Get format state at cursor
* A format state is a collection of all format related states, e.g.,
* bold, italic, underline, font name, font size, etc.
* @param editor The editor instance
* @param event (Optional) The plugin event, it stores the event cached data for looking up.
* In this function the event cache is used to get list state and header level. If not passed,
* it will query the node within selection to get the info
* @returns The format state at cursor
*/
export function getFormatState(editor: Editor, event?: PluginEvent): FormatState;
/**
* Get element based Format State at cursor
* @param editor The editor instance
* @param event (Optional) The plugin event, it stores the event cached data for looking up.
* In this function the event cache is used to get list state and header level. If not passed,
* it will query the node within selection to get the info
* @returns An ElementBasedFormatState object
*/
export function getElementBasedFormatState(editor: Editor, event?: PluginEvent): ElementBasedFormatState;
/**
* Get style based Format State at cursor
* @param editor The editor instance
* @returns A StyleBasedFormatState object
*/
export function getStyleBasedFormatState(editor: Editor): StyleBasedFormatState;
/**
* Insert an image to editor at current selection
* @param editor The editor instance
* @param imageFile The image file. There are at least 3 ways to obtain the file object:
* From local file, from clipboard data, from drag-and-drop
*/
export function insertImage(editor: Editor, imageFile: File): void;
/**
* Insert an image to editor at current selection
* @param editor The editor instance
* @param imageFile The image link.
*/
export function insertImage(editor: Editor, url: string): void;
/**
* Insert table into editor at current selection
* @param editor The editor instance
* @param columns Number of columns in table, it also controls the default table cell width:
* if columns <= 4, width = 120px; if columns <= 6, width = 100px; else width = 70px
* @param rows Number of rows in table
* @param format (Optional) The table format. If not passed, the default format will be applied:
* background color: #FFF; border color: #ABABAB
*/
export function insertTable(editor: Editor, columns: number, rows: number, format?: TableFormat): void;
/**
* Edit table with given operation. If there is no table at cursor then no op.
* @param editor The editor instance
* @param operation Table operation
*/
export function editTable(editor: Editor, operation: TableOperation): void;
/**
* Format table
* @param editor The editor which contains the table to format
* @param format A TableFormat object contains format information we want to apply to the table
* @param table The table to format. This is optional. When not passed, the current table (if any) will be formatted
*/
export function formatTable(editor: Editor, format: Partial<TableFormat>, table?: HTMLTableElement): void;
/**
* Remove link at selection. If no links at selection, do nothing.
* If selection contains multiple links, all of the link styles will be removed.
* If only part of a link is selected, the whole link style will be removed.
* @param editor The editor instance
*/
export function removeLink(editor: Editor): void;
/**
* Replace text before current selection with a node, current selection will be kept if possible
* @param editor The editor instance
* @param text The text for matching. We will try to match the text with the text before cursor
* @param node The node to replace the text with
* @param exactMatch True if the text must appear exactly before selection,
* otherwise there can be some text between the tearget text and selection
* @param searcher Optional PositionContentSearcher of current selection to help search text
*/
export function replaceWithNode(editor: Editor, text: string, node: Node, exactMatch: boolean, searcher?: PositionContentSearcher): boolean;
/**
* Replace a given range with a node, current selection will be kept if possible
* @param editor The editor instance
* @param range The range to replace from
* @param node The node to replace the text with
* @param exactMatch True if the text must appear exactly before selection,
* otherwise there can be some text between the tearget text and selection
*/
export function replaceWithNode(editor: Editor, range: Range, node: Node, exactMatch: boolean): boolean;
/**
* Set content alignment
* @param editor The editor instance
* @param alignment The alignment option:
* Alignment.Center, Alignment.Left, Alignment.Right
*/
export function setAlignment(editor: Editor, alignment: Alignment): void;
/**
* Set background color at current selection
* @param editor The editor instance
* @param color One of two options:
* The color string, can be any of the predefined color names (e.g, 'red')
* or hexadecimal color string (e.g, '#FF0000') or rgb value (e.g, 'rgb(255, 0, 0)') supported by browser.
* Currently there's no validation to the string, if the passed string is invalid, it won't take affect
* Alternatively, you can pass a @typedef ModeIndepenentColor. If in light mode, the lightModeColor property will be used.
* If in dark mode, the darkModeColor will be used and the lightModeColor will be used when converting back to light mode.
**/
export function setBackgroundColor(editor: Editor, color: string | ModeIndependentColor): void;
/**
* Set text color at selection
* @param editor The editor instance
* @param color One of two options:
* The color string, can be any of the predefined color names (e.g, 'red')
* or hexadecimal color string (e.g, '#FF0000') or rgb value (e.g, 'rgb(255, 0, 0)') supported by browser.
* Currently there's no validation to the string, if the passed string is invalid, it won't take affect
* Alternatively, you can pass a @typedef ModeIndepenentColor. If in light mode, the lightModeColor property will be used.
* If in dark mode, the darkModeColor will be used and the lightModeColor will be used when converting back to light mode.
*/
export function setTextColor(editor: Editor, color: string | ModeIndependentColor): void;
/**
* Change direction for the blocks/paragraph at selection
* @param editor The editor instance
* @param direction The direction option:
* Direction.LeftToRight refers to 'ltr', Direction.RightToLeft refers to 'rtl'
*/
export function setDirection(editor: Editor, direction: Direction): void;
/**
* Set font name at selection
* @param editor The editor instance
* @param fontName The fontName string, should be a valid CSS font-family style.
* Currently there's no validation to the string, if the passed string is invalid, it won't take affect
*/
export function setFontName(editor: Editor, fontName: string): void;
/**
* Set font size at selection
* @param editor The editor instance
* @param fontSize The fontSize string, should be a valid CSS font-size style.
* Currently there's no validation to the string, if the passed string is invalid, it won't take affect
*/
export function setFontSize(editor: Editor, fontSize: string): void;
/**
* Set image alt text for all selected images at selection. If no images is contained
* in selection, do nothing.
* The alt attribute provides alternative information for an image if a user for some reason
* cannot view it (because of slow connection, an error in the src attribute, or if the user
* uses a screen reader). See https: * @param editor The editor instance
* @param altText The image alt text
*/
export function setImageAltText(editor: Editor, altText: string): void;
/**
* Set indentation at selection
* If selection contains bullet/numbering list, increase/decrease indentation will
* increase/decrease the list level by one.
* @param editor The editor instance
* @param indentation The indentation option:
* Indentation.Increase to increase indentation or Indentation.Decrease to decrease indentation
*/
export function setIndentation(editor: Editor, indentation: Indentation): void;
/**
* Toggle bold at selection
* If selection is collapsed, it will only affect the following input after caret
* If selection contains only bold text, the bold style will be removed
* If selection contains only normal text, bold style will be added to the whole selected text
* If selection contains both bold and normal text, bold stle will be added to the whole selected text
* @param editor The editor instance
*/
export function toggleBold(editor: Editor): void;
/**
* Toggle bullet at selection
* If selection contains bullet in deep level, toggle bullet will decrease the bullet level by one
* If selection contains number list, toggle bullet will convert the number list into bullet list
* If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding
* browser execCommand API
* @param editor The editor instance
*/
export function toggleBullet(editor: Editor): void;
/**
* Toggle italic at selection
* If selection is collapsed, it will only affect the input after caret
* If selection contains only italic text, the italic style will be removed
* If selection contains only normal text, italic style will be added to the whole selected text
* If selection contains both italic and normal text, italic stlye will be added to the whole selected text
* @param editor The editor instance
*/
export function toggleItalic(editor: Editor): void;
/**
* Toggle numbering at selection
* If selection contains numbering in deep level, toggle numbering will decrease the numbering level by one
* If selection contains bullet list, toggle numbering will convert the bullet list into number list
* If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding
* realization of browser execCommand API
* @param editor The editor instance
*/
export function toggleNumbering(editor: Editor): void;
/**
* Toggle blockquote at selection, if selection already contains any blockquoted elements,
* the blockquoted elements will be unblockquoted and other elements will take no affect
* @param editor The editor instance
* @param styler (Optional) The custom styler for setting the style for the blockquote element
*/
export function toggleBlockQuote(editor: Editor, styler?: (element: HTMLElement) => void): void;
/**
* Toggle code block at selection, if selection already contains any code blocked elements,
* the code block elements will be no longer be code blocked and other elements will take no affect
* @param editor The editor instance
* @param styler (Optional) The custom styler for setting the style for the code block element
*/
export function toggleCodeBlock(editor: Editor, styler?: (element: HTMLElement) => void): void;
/**
* Toggle strikethrough at selection
* If selection is collapsed, it will only affect the input after caret
* If selection contains only strikethrough text, the strikethrough style will be removed
* If selection contains only normal text, strikethrough style will be added to the whole selected text
* If selection contains both strikethrough and normal text, strikethrough stlye will be added to the whole selected text
* @param editor The editor instance
*/
export function toggleStrikethrough(editor: Editor): void;
/**
* Toggle subscript at selection
* If selection is collapsed, it will only affect the input after caret
* If selection contains only subscript text, the subscript style will be removed
* If selection contains only normal text, subscript style will be added to the whole selected text
* If selection contains both subscript and normal text, the subscript style will be removed from whole selected text
* If selection contains any superscript text, the behavior is determined by corresponding realization of browser
* execCommand API
* @param editor The editor instance
*/
export function toggleSubscript(editor: Editor): void;
/**
* Toggle superscript at selection
* If selection is collapsed, it will only affect the input after caret
* If selection contains only superscript text, the superscript style will be removed
* If selection contains only normal text, superscript style will be added to the whole selected text
* If selection contains both superscript and normal text, the superscript style will be removed from whole selected text
* If selection contains any subscript text, the behavior is determined by corresponding realization of browser
* execCommand API
* @param editor The editor instance
*/
export function toggleSuperscript(editor: Editor): void;
/**
* Toggle underline at selection
* If selection is collapsed, it will only affect the input after caret
* If selection contains only underlined text, the underline style will be removed
* If selection contains only normal text, underline style will be added to the whole selected text
* If selection contains both underlined and normal text, the underline style will be added to the whole selected text
* @param editor The editor instance
*/
export function toggleUnderline(editor: Editor): void;
/**
* Toggle header at selection
* @param editor The editor instance
* @param level The header level, can be a number from 0 to 6, in which 1 ~ 6 refers to
* the HTML header element <H1> to <H6>, 0 means no header
* if passed in param is outside the range, will be rounded to nearest number in the range
*/
export function toggleHeader(editor: Editor, level: number): void;
/**
* An editor plugin to handle content edit event.
* The following cases are included:
* 1. Auto increase/decrease indentation on Tab, Shift+tab
* 2. Enter, Backspace on empty list item
* 3. Enter, Backspace on empty blockquote line
* 4. Auto bullet/numbering
* 5. Auto link
* 6. Tab in table
* 7. Up/Down in table
* 8. Manage list style
*/
export class ContentEdit implements EditorPlugin {
private featureSet?;
private editor;
/**
* Create instance of ContentEdit plugin
* @param features An optional feature set to determine which features the plugin should provide
*/
constructor(featureSet?: ContentEditFeatures);
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin
* @param editor The editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
private getFilteredFeatures;
}
/**
* Feature set for ContentEdit plugin.
* Call getDefaultContentEditFeatures() to get default feature set.
*/
export interface ContentEditFeatures {
/**
* When press Tab in a list, indent current list item
* @default true
*/
indentWhenTab: boolean;
/**
* When press Shift+Tab in a list, outdent current list item
* @default true
*/
outdentWhenShiftTab: boolean;
/**
* When press BaskSpace on empty line which is the first item of a list, outdent current list item
* @default true
*/
outdentWhenBackspaceOnEmptyFirstLine: boolean;
/**
* When press Enter on empty line in a list, outdent current list item
* @default true for IE, false for other browsers since they have already had the behavior
*/
outdentWhenEnterOnEmptyLine: boolean;
/**
* When press Backspace on first char in a list, make current item a new line of previous list item
* @default false
*/
mergeInNewLineWhenBackspaceOnFirstChar: boolean;
/**
* When press BAckspace on empty line which is the first line of a blockquote, unquote current line
* @default true
*/
unquoteWhenBackspaceOnEmptyFirstLine: boolean;
/**
* When press Enter on empty line in a blockquote, unquote current line
* @default true
*/
unquoteWhenEnterOnEmptyLine: boolean;
/**
* When press space after an asterik or number in an empty line, toggle bullet/numbering
* @default true
*/
autoBullet: boolean;
/**
* When press TAB or SHIFT+TAB key in table cell, jump to next/previous table cell
* @default true
*/
tabInTable: boolean;
/**
* When press Up or Down in table cell, jump to the table cell above/below
* @default true for Chrome and safari, false for other browsers since they arleady have correct behavior
*/
upDownInTable: boolean;
/**
* When press Enter at the beginning of first structured element (table, list) and there isn't line before the position
* we create a new line before so that user got a chance to enter content before the table or list
* @default false
*/
insertLineBeforeStructuredNodeFeature: boolean;
/**
* When press Space or Enter after a hyperlink-like string, convert the string to a hyperlink
* @default true
*/
autoLink: boolean;
/**
* Respond to default common keyboard short, i.e. Ctrl+B, Ctrl+I, Ctrl+U, Ctrl+Z, Ctrl+Y
* @default true
*/
defaultShortcut: boolean;
/**
* Unlink when backspace right after a hyperlink
* @default false
*/
unlinkWhenBackspaceAfterLink: boolean;
/**
* Chrome may make the cursor move the then end of document if press Ctrl+Left at the beginning of document
* Let's disable this behaivor
*/
noCycleCursorMove: boolean;
/**
* When generate ordered list, the list bullet will variare according its nesting level, in a loop of '1', 'a', 'i'
* @default false
*/
smartOrderedList: boolean;
/**
* A style list for smart ordered list. This value is only effective when smartOrderedList is true
* @default ['lower-alpha', 'lower-roman', 'decimal']
*/
smartOrderedListStyles: string[];
}
/**
* Get default feature set of ContentEdit plugin
*/
export function getDefaultContentEditFeatures(): ContentEditFeatures;
/**
* Wrapper for CustomReplaceContentEditFeature that provides an API for updating the
* content edit feature
*/
export class CustomReplace implements EditorPlugin {
private longestReplacementLength;
private editor;
private replacements;
private replacementEndCharacters;
/**
* Create instance of CustomReplace plugin
* @param replacements Replacement rules. If not passed, a default replacement rule set will be applied
*/
constructor(replacements?: Replacement[]);
/**
* Set the replacements that this plugin is looking for.
* @param newReplacements new set of replacements for this plugin
*/
updateReplacements(newReplacements: Replacement[]): void;
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin
* @param editor The editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
onPluginEvent(event: PluginEvent): void;
private getMatchingReplacement;
}
/**
* An interface to define a replacement rule for CustomReplace plugin
*/
export interface Replacement {
/**
* Source string to replace from
*/
sourceString: string;
/**
* HTML string to replace to
*/
replacementHTML: string;
/**
* Whether the matching should be case sensitive
*/
matchSourceCaseSensitive: boolean;
}
/**
* An editor plugin that show a tooltip for existing link
*/
export class HyperLink implements EditorPlugin {
private getTooltipCallback;
private target?;
private onLinkClick?;
private editor;
private disposer;
/**
* Create a new instance of HyperLink class
* @param getTooltipCallback A callback function to get tooltip text for an existing hyperlink.
* Default value is to return the href itself. If null, there will be no tooltip text.
* @param target (Optional) Target window name for hyperlink. If null, will use "_blank"
* @param onLinkClick (Optional) Open link callback (return false to use default behavior)
*/
constructor(getTooltipCallback?: (href: string, a: HTMLAnchorElement) => string, target?: string, onLinkClick?: (anchor: HTMLAnchorElement, mouseEvent: MouseEvent) => boolean | void);
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin
* @param editor The editor instance
*/
initialize(editor: Editor): void;
protected onMouse: (e: MouseEvent) => void;
/**
* Dispose this plugin
*/
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
/**
* Try get href from an anchor element
* The reason this is put in a try-catch is that
* it has been seen that accessing href may throw an exception, in particular on IE/Edge
*/
private tryGetHref;
}
/**
* ImageResize plugin provides the ability to resize an inline image in editor
*/
export class ImageResize implements EditorPlugin {
private minWidth;
private minHeight;
private selectionBorderColor;
private forcePreserveRatio;
private resizableImageSelector;
private editor;
private startPageX;
private startPageY;
private startWidth;
private startHeight;
private resizeDiv;
private direction;
private disposer;
/**
* Create a new instance of ImageResize
* @param minWidth Minimum width of image when resize in pixel, default value is 10
* @param minHeight Minimum height of image when resize in pixel, default value is 10
* @param selectionBorderColor Color of resize border and handles, default value is #DB626C
* @param forcePreserveRatio Whether always preserve width/height ratio when resize, default value is false
* @param resizableImageSelector Selector for picking which image is resizable (e.g. for all images not placeholders), note
* that the tag must be IMG regardless what the selector is
*/
constructor(minWidth?: number, minHeight?: number, selectionBorderColor?: string, forcePreserveRatio?: boolean, resizableImageSelector?: string);
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(e: PluginEvent): void;
/**
* Select a given IMG element, show the resize handle
* @param img The IMG element to select
*/
showResizeHandle(img: HTMLImageElement): void;
/**
* Hide resize handle of current selected image
* @param selectImageAfterUnSelect Optional, when set to true, select the image element after hide the resize handle
*/
hideResizeHandle(selectImageAfterUnSelect?: boolean): void;
private startResize;
private doResize;
private finishResize;
private createResizeDiv;
private stopEvent;
private removeResizeDiv;
private removeResizeDivIfAny;
private onBlur;
private extractHtml;
private getSelectedImage;
private isNorth;
private isWest;
private onDragStart;
}
/**
* Paste plugin, handles onPaste event and paste content into editor
*/
export class Paste implements EditorPlugin {
private editor;
private pasteDisposer;
private sanitizer;
/**
* Create an instance of Paste
* @param preserved Not used. Preserved parameter only used for compatibility with old code
* @param attributeCallbacks A set of callbacks to help handle html attribute during sanitization
*/
constructor(preserved?: any, attributeCallbacks?: AttributeCallbackMap);
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
private onPaste;
/**
* Paste into editor using passed in clipboardData with original format
* @param clipboardData The clipboardData to paste
*/
pasteOriginal(clipboardData: ClipboardData): void;
/**
* Paste plain text into editor using passed in clipboardData
* @param clipboardData The clipboardData to paste
*/
pasteText(clipboardData: ClipboardData): void;
/**
* Paste into editor using passed in clipboardData with curent format
* @param clipboardData The clipboardData to paste
*/
pasteAndMergeFormat(clipboardData: ClipboardData): void;
private detectPasteOption;
private paste;
private internalPaste;
private applyFormatting;
private applyToElements;
private getCurrentFormat;
private sanitizeHtml;
}
/**
* PickerPlugin represents a plugin of editor which can handle picker related behaviors, including
* - Show picker when special trigger key is pressed
* - Hide picker
* - Change selection in picker by Up/Down/Left/Right
* - Apply selected item in picker
*
* PickerPlugin doesn't provide any UI, it just wraps related DOM events and invoke callback functions.
* To show a picker UI, you need to build your own UI component. Please reference to
* https: */
export class PickerPlugin<T extends PickerDataProvider = PickerDataProvider> implements EditorPickerPluginInterface<T> {
readonly dataProvider: T;
private pickerOptions;
private editor;
private eventHandledOnKeyDown;
private blockSuggestions;
private isSuggesting;
private lastKnownRange;
private isPendingInputEventHandling;
private currentInputLength;
private newInputLength;
constructor(dataProvider: T, pickerOptions: PickerPluginOptions);
/**
* Get a friendly name
*/
getName(): string;
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
/**
* Check if the plugin should handle the given event exclusively.
* Handle an event exclusively means other plugin will not receive this event in
* onPluginEvent method.
* If two plugins will return true in willHandleEventExclusively() for the same event,
* the final result depends on the order of the plugins are added into editor
* @param event The event to check
*/
willHandleEventExclusively(event: PluginEvent): boolean;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
private setLastKnownRange;
private setIsSuggesting;
private cancelDefaultKeyDownEvent;
private getIdValue;
private getWordBeforeCursor;
private replaceNode;
private getRangeUntilAt;
private shouldHandleKeyUpEvent;
private onKeyUpDomEvent;
private onKeyDownEvent;
private onAndroidInputEvent;
private calcInputLength;
private tryRemoveNode;
private getWord;
private setRangeStart;
private setAriaOwns;
private setAriaActiveDescendant;
private getInlineElementBeforeCursor;
}
/**
* Interface for PickerPlugin
*/
export interface EditorPickerPluginInterface<T extends PickerDataProvider = PickerDataProvider> extends EditorPlugin {
dataProvider: T;
}
/**
* Options for PickerPlugin
*/
export interface PickerPluginOptions {
/**
* Constant that defines the element ID prefix to look for.
* If it matches, this element should be handled by the plugin
*/
elementIdPrefix: string;
/**
* When apply the selected item in picker, a ContentChangedEvent will be broadcasted.
* This value will be used as the ChangeSource of this event.
*/
changeSource: string;
/**
* Constant that defines the character(s) that will trigger the suggesting state in the plugin.
*/
triggerCharacter: string;
/**
* Option for using the picker in the horizontal state:
* Vertical (the default, when this is false), will call shiftHighlight with up (false) and down (true).
* Horizontal (when this is true), will call shiftHighlight with left (false) and right (true).
*/
isHorizontal?: boolean;
/**
* When apply the selected item in picker, perform as an auto-complete behavior (can be undone by BACKSPACE key)
* if this option is set to true
*/
handleAutoComplete?: boolean;
/**
* Constant that defines the ID label for the picker.
* Used for setting the ariaOwns attribute of the editor when a picker is open.
*/
suggestionsLabel?: string;
/**
* Constant that defines the prefix of the ID label for the picker's options.
* Used for setting the ariaActiveDescendant attribute of the editor when a picker option is selected.
*/
suggestionLabelPrefix?: string;
}
/**
* Data provider for PickerPlugin
*/
export interface PickerDataProvider {
/**
* Function called when the plugin is intialized to register two callbacks with the data provider and a reference to the Editor.
* The first is called in order to "commit" a new element to the editor body that isn't handled automatically by the editor plugin.
* The second sets the isSuggesting value for situations wherethe UX needs to manipulate the suggesting state that's otherwise plugin managed.
*/
onInitalize: (insertNodeCallback: (nodeToInsert: HTMLElement) => void, setIsSuggestingCallback: (isSuggesting: boolean) => void, editor?: Editor) => void;
/**
* Function called when the plugin is disposed for the data provider to do any cleanup.
*/
onDispose: () => void;
/**
* Function called when the picker changes suggesting state.
*/
onIsSuggestingChanged: (isSuggesting: boolean) => void;
/**
* Function called when the query string (text after the trigger symbol) is updated.
*/
queryStringUpdated: (queryString: string, isExactMatch: boolean) => void;
/**
* Function called when a keypress is issued that would "select" a currently highlighted option.
*/
selectOption?: () => void;
/**
* Function called when a keypress is issued that would move the highlight on any picker UX.
*/
shiftHighlight?: (isIncrement: boolean) => void;
/**
* Function that is called when a delete command is issued.
* Returns the intended replacement node (if partial delete) or null (if full delete)
*/
onRemove: (nodeRemoved: Node, isBackwards: boolean) => Node;
/**
* Function that returns the current cursor position as an anchor point for where to show UX.
*/
setCursorPoint?: (targetPoint: {
x: number;
y: number;
}, buffer: number) => void;
/**
* Function that is called when the plugin detects the editor's content has changed.
* Provides a list of current picker placed elements in the document.
*/
onContentChanged?: (elementIds: string[]) => void;
/**
* Function that returns the index of the option currently selected in the picker.
*/
getSelectedIndex?: () => number;
/**
* Handler of scroll event from scroll container of editor
*/
onScroll?: (scrollContainer: HTMLElement) => void;
}
/**
* TableResize plugin, provides the ability to resize a table by drag-and-drop
*/
export class TableResize implements EditorPlugin {
private editor;
private onMouseOverDisposer;
private td;
private pageX;
private initialPageX;
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: Editor): void;
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Dispose this plugin
*/
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
private clickIntoCurrentTd;
private onMouseOver;
private calcAndShowHandle;
private adjustHandle;
private getPosition;
private getResizeHandle;
private cancelEvent;
private onMouseDown;
private onMouseMove;
private onMouseUp;
private attachMouseEvents;
private detachMouseEvents;
private setTableColumnWidth;
}
/**
* A watermark plugin to manage watermark string for roosterjs
*/
export class Watermark implements EditorPlugin {
private watermark;
private format?;
private editor;
private isWatermarkShowing;
private disposer;
private spellcheckInitialValue;
/**
* Create an instance of Watermark plugin
* @param watermark The watermark string
*/
constructor(watermark: string, format?: DefaultFormat);
/**
* Get a friendly name of this plugin
*/
getName(): string;
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: Editor): void;
/**
* Dispose this plugin
*/
dispose(): void;
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent): void;
private handleWatermark;
private showHideWatermark;
private showWatermark;
private hideWatermark;
private removeWartermarkFromHtml;
}
/**
* Entity Plugin helps handle all operations related to an entity and generate entity specified events
*/
export class EntityPlugin implements EditorPlugin {
private editor;
private disposer;
private clickingPoint;
private knownEntityElements;
getName(): string;
initialize(editor: Editor): void;
dispose(): void;
onPluginEvent(event: PluginEvent): void;
private handleContextMenuEvent;
private handleCutEvent;
private handleMouseDownEvent;
private handleMouseUpEvent;
private handleKeyDownEvent;
private handleBeforePasteEvent;
private handleContentChangedEvent;
private handleExtractContentWithDomEvent;
private checkRemoveEntityForRange;
}
/**
* Insert an entity into editor.
* @param editor The editor to insert entity into.
* @param type Type of the entity
* @param contentNode Root element of the entity
* @param isBlock Whether the entity will be shown as a block
* @param isReadonly Whether the entity will be a readonly entity
* @param position (Optional) The position to insert into. If not specified, current position will be used.
* If isBlock is true, entity will be insert below this position
*/
export function insertEntity(editor: Editor, type: string, contentNode: Node, isBlock: boolean, isReadonly: boolean, position?: NodePosition): Entity;
/**
* Get Entity object from an entity root element
* @param element The entity root element. If this element is not an entity root element,
* it will return null
*/
export function getEntityFromElement(element: HTMLElement): Entity;
/**
* Get all entities with given entity type and id from an editor
* @param editor The editor to get entity from
* @param type (Optional) Type of the entity. If not specified, it will return all entities from this editor
* @param id (Optional) Id of the entity. If not specified, it will return all entities of the given type
*/
export function getEntities(editor: Editor, type?: string, id?: string): Entity[];
/**
* Get the entity element from a child (or the element itself) of an entity.
* If the given node is not part of an entity, it will return null
* @param editor The editor to get entity from
* @param node The child node
*/
export function getEntityElement(editor: Editor, node: Node): HTMLElement;