@toast-ui/editor
Version:
GFM Markdown Wysiwyg Editor - Productive and Extensible
333 lines (220 loc) • 7.96 kB
TypeScript
import { Schema, NodeSpec, Fragment } from 'prosemirror-model';
import { EditorView, Decoration, DecorationSet } from 'prosemirror-view';
import { EditorState, Plugin, Selection, TextSelection } from 'prosemirror-state';
import { HTMLConvertorMap, MdPos, Sourcepos } from '@toast-ui/toastmark';
import { Emitter, Handler } from './event';
import { Context, EditorAllCommandMap, EditorCommandFn, SpecManager } from './spec';
import { ToMdConvertorMap } from './convertor';
import { DefaultUI, ToolbarItemOptions } from './ui';
import { CommandFn, PluginInfo } from './plugin';
export type PreviewStyle = 'tab' | 'vertical';
export type EditorType = 'markdown' | 'wysiwyg';
export type WidgetStyle = 'top' | 'bottom';
export interface WidgetRule {
rule: RegExp;
toDOM: (text: string) => HTMLElement;
}
export type WidgetRuleMap = Record<string, WidgetRule>;
export interface EventMap {
load?: (param: Editor) => void;
change?: (editorType: EditorType) => void;
caretChange?: (editorType: EditorType) => void;
focus?: (editorType: EditorType) => void;
blur?: (editorType: EditorType) => void;
keydown?: (editorType: EditorType, ev: KeyboardEvent) => void;
keyup?: (editorType: EditorType, ev: KeyboardEvent) => void;
beforePreviewRender?: (html: string) => string;
beforeConvertWysiwygToMarkdown?: (markdownText: string) => string;
}
type HookCallback = (url: string, text?: string) => void;
export type HookMap = {
addImageBlobHook?: (blob: Blob | File, callback: HookCallback) => void;
};
export type AutolinkParser = (
content: string
) => {
url: string;
text: string;
range: [number, number];
}[];
export type ExtendedAutolinks = boolean | AutolinkParser;
export type LinkAttributeNames = 'rel' | 'target' | 'hreflang' | 'type';
// @TODO change option and type name from singular to plural
export type LinkAttributes = Partial<Record<LinkAttributeNames, string>>;
export type Sanitizer = (content: string) => string;
export interface ViewerOptions {
el: HTMLElement;
initialValue?: string;
events?: EventMap;
plugins?: EditorPlugin[];
extendedAutolinks?: ExtendedAutolinks;
linkAttributes?: LinkAttributes;
customHTMLRenderer?: HTMLConvertorMap;
referenceDefinition?: boolean;
customHTMLSanitizer?: Sanitizer;
frontMatter?: boolean;
usageStatistics?: boolean;
theme?: string;
}
export class Viewer {
static isViewer: boolean;
constructor(options: ViewerOptions);
setMarkdown(markdown: string): void;
on(type: string, handler: Handler): void;
off(type: string): void;
destroy(): void;
isViewer(): boolean;
isMarkdownMode(): boolean;
isWysiwygMode(): boolean;
addHook(type: string, handler: Handler): void;
}
export interface I18n {
setCode(code?: string): void;
setLanguage(codes: string | string[], data: Record<string, string>): void;
get(key: string, code?: string): string;
}
export interface PluginContext {
eventEmitter: Emitter;
usageStatistics?: boolean;
i18n: I18n;
pmState: {
Plugin: typeof Plugin;
Selection: typeof Selection;
TextSelection: typeof TextSelection;
};
pmView: { Decoration: typeof Decoration; DecorationSet: typeof DecorationSet };
pmModel: { Fragment: typeof Fragment };
}
export type PluginFn = (context: PluginContext, options?: Record<string, any>) => PluginInfo | null;
export type EditorPlugin = PluginFn | [PluginFn, Record<string, any>];
export interface EditorOptions {
el: HTMLElement;
height?: string;
minHeight?: string;
initialValue?: string;
previewStyle?: PreviewStyle;
initialEditType?: EditorType;
events?: EventMap;
hooks?: HookMap;
language?: string;
useCommandShortcut?: boolean;
usageStatistics?: boolean;
toolbarItems?: (string | ToolbarItemOptions)[];
hideModeSwitch?: boolean;
plugins?: EditorPlugin[];
extendedAutolinks?: ExtendedAutolinks;
placeholder?: string;
linkAttributes?: LinkAttributes;
customHTMLRenderer?: HTMLConvertorMap;
customMarkdownRenderer?: ToMdConvertorMap;
referenceDefinition?: boolean;
customHTMLSanitizer?: Sanitizer;
previewHighlight?: boolean;
frontMatter?: boolean;
widgetRules?: WidgetRule[];
theme?: string;
}
interface Slots {
mdEditor: HTMLElement;
mdPreview: HTMLElement;
wwEditor: HTMLElement;
}
export class EditorCore {
constructor(options: EditorOptions);
public eventEmitter: Emitter;
public static factory(options: EditorOptions): EditorCore | Viewer;
public static setLanguage(code: string, data: Record<string, string>): void;
changePreviewStyle(style: PreviewStyle): void;
exec(name: string, payload?: Record<string, any>): void;
addCommand(type: EditorType, name: string, command: CommandFn): void;
on(type: string, handler: Handler): void;
off(type: string): void;
addHook(type: string, handler: Handler): void;
removeHook(type: string): void;
focus(): void;
blur(): void;
moveCursorToEnd(): void;
moveCursorToStart(): void;
setMarkdown(markdown: string, cursorToEnd?: boolean): void;
setHTML(html: string, cursorToEnd?: boolean): void;
getMarkdown(): string;
getHTML(): string;
insertText(text: string): void;
setSelection(start: EditorPos, end?: EditorPos): void;
replaceSelection(text: string, start?: EditorPos, end?: EditorPos): void;
deleteSelection(start?: EditorPos, end?: EditorPos): void;
getSelectedText(start?: EditorPos, end?: EditorPos): string;
getRangeInfoOfNode(pos?: EditorPos): NodeRangeInfo;
addWidget(node: Node, style: WidgetStyle, pos?: EditorPos): void;
replaceWithWidget(start: EditorPos, end: EditorPos, text: string): void;
setHeight(height: string): void;
getHeight(): string;
setMinHeight(minHeight: string): void;
getMinHeight(): string;
isMarkdownMode(): boolean;
isWysiwygMode(): boolean;
isViewer(): boolean;
getCurrentPreviewStyle(): PreviewStyle;
changeMode(mode: EditorType, isWithoutFocus?: boolean): void;
destroy(): void;
hide(): void;
show(): void;
setScrollTop(value: number): void;
getScrollTop(): number;
reset(): void;
getSelection(): SelectionPos;
setPlaceholder(placeholder: string): void;
getEditorElements(): Slots;
}
export class Editor extends EditorCore {
getDefaultUI(): DefaultUI;
}
export type SelectionPos = Sourcepos | [from: number, to: number];
export type EditorPos = MdPos | number;
export interface NodeRangeInfo {
range: SelectionPos;
type: string;
}
export interface Base {
el: HTMLElement;
editorType: EditorType;
eventEmitter: Emitter;
context: Context;
schema: Schema;
keymaps: Plugin[];
view: EditorView;
commands: EditorAllCommandMap;
specs: SpecManager;
placeholder: { text: string };
createSpecs(): SpecManager;
createContext(): Context;
createState(): EditorState;
createView(): EditorView;
createSchema(): Schema;
createKeymaps(useCommandShortcut: boolean): Plugin<any, any>[];
createCommands(): Record<string, EditorCommandFn<Record<string, any>>>;
focus(): void;
blur(): void;
destroy(): void;
moveCursorToStart(): void;
moveCursorToEnd(): void;
setScrollTop(top: number): void;
getScrollTop(): number;
setPlaceholder(text: string): void;
setHeight(height: number): void;
setMinHeight(minHeight: number): void;
getElement(): HTMLElement;
setSelection(start: EditorPos, end?: EditorPos): void;
replaceWithWidget(start: EditorPos, end: EditorPos, text: string): void;
addWidget(node: Node, style: WidgetStyle, pos?: EditorPos): void;
replaceSelection(text: string, start?: EditorPos, end?: EditorPos): void;
deleteSelection(start?: EditorPos, end?: EditorPos): void;
getSelectedText(start?: EditorPos, end?: EditorPos): string;
getSelection(): SelectionPos;
getRangeInfoOfNode(pos?: EditorPos): NodeRangeInfo;
}
export type SchemaMap = Record<string, NodeSpec | MarkSpec>;
export interface HTMLSchemaMap {
nodes: SchemaMap;
marks: SchemaMap;
}