// 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 &lt;color&gt; 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 &lt;strong&gt; tag instead of &lt;b&gt;.
     */
    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 &lt;small&gt; 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, &lt;blockquote&gt; 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 "&lt;H1&gt;".)
     */
    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 &lt;big&gt; 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 &lt;br&gt; element, or splits the current block element into two.
     * (Not supported by Internet Explorer.)
     */
    InsertBrOnReturn = "insertBrOnReturn",
    /**
     * Inserts a &lt;hr&gt; 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 &lt;em&gt; element instead of &lt;i&gt;.)
     */
    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 &lt;p&gt; or &lt;div&gt;.
     */
    Element = 1,
    /**
     * The actual Text of Element or Attr.
     */
    Text = 3,
    /**
     * A ProcessingInstruction of an XML document such as &lt;?xml-stylesheet ... ?&gt; declaration.
     */
    ProcessingInstruction = 7,
    /**
     * A Comment node.
     */
    Comment = 8,
    /**
     * A Document node.
     */
    Document = 9,
    /**
     * A DocumentType node e.g. &lt;!DOCTYPE html&gt; 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. &lt;p&gt;, &lt;div&gt;, &lt;li&gt;, &lt;td&gt; etc.
 * but can also be just a text node, followed by a &lt;br&gt;, i.e.
 * for html fragment &lt;div&gt;abc&lt;br&gt;123&lt;/div&gt;, abc&lt;br&gt; 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 &lt;B&gt; 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) &lt;root&gt;&lt;div&gt;abc&lt;/div&gt;&lt;/root&gt;
 *   This is most common the case, user passes in a node pointing to abc, and get back a block representing &lt;div&gt;abc&lt;/div&gt;
 * 2) &lt;root&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;/root&gt;
 *   Common content for empty block, user passes node pointing to &lt;br&gt;, and get back a block representing &lt;p&gt;&lt;br&gt;&lt;/p&gt;
 * 3) &lt;root&gt;abc&lt;/root&gt;
 *   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) &lt;root&gt;&lt;div&gt;abc&lt;br&gt;123&lt;/div&gt;&lt;/root&gt;
 *   A bit tricky, but can happen when user use Ctrl+Enter which simply inserts a &lt;BR&gt; to create a link break. There're two blocks:
 *   block1: 1) abc&lt;br&gt; block2: 123
 * 5) &lt;root&gt;&lt;div&gt;abc&lt;div&gt;123&lt;/div&gt;&lt;/div&gt;&lt;/root&gt;
 *   Nesting div and there is text node in same level as a DIV. Two blocks: 1) abc 2) &lt;div&gt;123&lt;/div&gt;
 * 6) &lt;root&gt;&lt;div&gt;abc&lt;span&gt;123&lt;br&gt;456&lt;/span&gt;&lt;/div&gt;&lt;/root&gt;
 *   This is really tricky. Essentially there is a &lt;BR&gt; in middle of a span breaking the span into two blocks;
 *   block1: abc&lt;span&gt;123&lt;br&gt; 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 &lt;root&gt;Hello&lt;BR&gt;World&lt;/root&gt;
 * in that case, Hello&lt;BR&gt; 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 &lt;!--StartFragment--&gt; and &lt;!--Endfragment--&gt;
     * @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 (&lt;!--StartFragment--&gt; and &lt;!--EndFragment--&gt;),
 * 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 &lt;= 4, width = 120px; if columns &lt;= 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 &lt;H1&gt; to &lt;H6&gt;, 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;

