prism-code-editor
Version:
Lightweight, extensible code editor component for the web using Prism
155 lines (154 loc) • 7.53 kB
TypeScript
import { BracketMatcher } from './extensions/matchBrackets/index.js';
import { TagMatcher } from './extensions/matchTags.js';
import { Cursor } from './extensions/cursor.js';
import { SearchWidget } from './extensions/search/widget.js';
import { ReadOnlyCodeFolding } from './extensions/folding/index.js';
import { TokenStream } from './prism/types.js';
import { EditHistory } from './extensions/commands.js';
export type EditorOptions = {
/**
* Language used for syntax highlighting. If the language doesn't have a registered
* Prism grammar, syntax highlighting will be disabled. @default "text"
*/
language: string;
/** Tabsize for the editor. @default 2 */
tabSize?: number | undefined;
/** Whether the editor should insert spaces for indentation. @default true */
insertSpaces?: boolean | undefined;
/** Whether line numbers should be shown. @default true */
lineNumbers?: boolean | undefined;
/** Whether the editor should be read only. @default false */
readOnly?: boolean | undefined;
/** Whether the editor should have word wrap. @default false */
wordWrap?: boolean | undefined;
/** Code to display in the editor. */
value: string;
/**
* Whether the editor uses right to left directionality. Requires styles from
* `prism-code-editor/rtl-layout.css` to work unless the setups are used.
* @default false
*/
rtl?: boolean;
/**
* Additional classes for the root container. Useful to style individual editors.
* The `.prism-code-editor` selector can be used to style all editors.
*/
class?: string;
/** Function called when the code of the editor changes. */
onUpdate?: EditorEventMap["update"] | null;
/** Function called when the selection changes in the editor. */
onSelectionChange?: EditorEventMap["selectionChange"] | null;
/** Function called before the tokens are stringified to HTML. */
onTokenize?: EditorEventMap["tokenize"] | null;
};
export type CommentTokens = {
line?: string;
block?: [string, string];
};
export type Language = {
/** Comment tokens used by the language. */
comments?: CommentTokens;
/**
* Method called when a user executes a comment toggling command.
* @param editor The editor the user is interacting with.
* @param position Where in the code the comment is being toggled.
* @param value Current code in the editor.
* @returns The comment tokens that should be used for this command.
*/
getComments?(editor: PrismEditor, position: number, value: string): CommentTokens;
/**
* Callbacks controlling the automatic indentation on new lines.
* First function should return whether indentation should be increased.
* Second function should return whether to add an extra line after the cursor.
*/
autoIndent?: [
((selection: InputSelection, value: string, editor: PrismEditor) => boolean)?,
((selection: InputSelection, value: string, editor: PrismEditor) => boolean)?
];
/**
* Function called when the user types `>`. Intended to auto close tags.
* @returns string which will get inserted behind the cursor.
*/
autoCloseTags?(selection: InputSelection, value: string, editor: PrismEditor): string | undefined;
};
/**
* Function called when a certain key is pressed.
* If true is returned, `e.preventDefault()` and `e.stopImmediatePropagation()` is called automatically.
*/
export type KeyCommandCallback = (e: KeyboardEvent, selection: InputSelection, value: string) => void | boolean;
/**
* Function called when a certain input is typed.
* If true is returned, `e.preventDefault()` and `e.stopImmediatePropagation()` is called automatically.
*/
export type InputCommandCallback = (e: InputEvent, selection: InputSelection, value: string) => void | boolean;
export type InputSelection = [number, number, "forward" | "backward" | "none"];
export interface Extension<T extends {} = {}> {
/** Function called when the extension is added or the options of the editor change. */
update(editor: PrismEditor<T>, options: EditorOptions & Omit<T, keyof EditorOptions>): any;
}
export interface BasicExtension<T extends {} = {}> {
(editor: PrismEditor<T>, options: EditorOptions & T): any;
}
export type EditorExtension<T extends {} = {}> = Extension<T> | BasicExtension<T>;
export type EditorEventMap<T extends {} = {}> = {
update(this: PrismEditor<T>, value: string): any;
selectionChange(this: PrismEditor<T>, selection: InputSelection, value: string): any;
tokenize(this: PrismEditor<T>, tokens: TokenStream, language: string, value: string): any;
};
export interface PrismEditor<T extends {} = {}> {
/** This is the outermost element of the editor. */
readonly container: HTMLDivElement;
/** Element wrapping the lines and overlays. */
readonly wrapper: HTMLDivElement;
/**
* Collection containing the overlays as the first element. The rest of the elements
* are the code lines. This means the index of a line is the same as its line number.
*/
readonly lines: HTMLCollectionOf<HTMLDivElement>;
/** Underlying `<textarea>` in the editor. */
readonly textarea: HTMLTextAreaElement;
/**
* The line number of the line the cursor is currently on. You can use
* `editor.lines[editor.activeLine]` to get the element for the active line.
*/
readonly activeLine: number;
/** Whether the `textarea` is focused. */
readonly focused: boolean;
/** Current code in the editor. Same as `textarea.value`. */
readonly value: string;
/**
* Current options for the editor. The event handlers can be changed by
* mutating this object. Use `setOptions` to change the other options.
*/
readonly options: EditorOptions & Omit<T, keyof EditorOptions>;
/** Record mapping an input to a function called when that input is typed. */
readonly inputCommandMap: Record<string, InputCommandCallback | null | undefined>;
/** Record mapping KeyboardEvent.key to a function called when that key is pressed. */
readonly keyCommandMap: Record<string, KeyCommandCallback | null | undefined>;
/** Tokens currently displayed in the editor. */
readonly tokens: TokenStream;
/** Object storing some of the extensions added to the editor. */
readonly extensions: {
matchBrackets?: BracketMatcher;
matchTags?: TagMatcher;
cursor?: Cursor;
searchWidget?: SearchWidget;
codeFold?: ReadOnlyCodeFolding;
history?: EditHistory;
};
/**
* Set new options for the editor. Omitted properties will use their old value.
* @param options New options for the editor
*/
setOptions(this: void, options: Partial<EditorOptions & Omit<T, keyof EditorOptions>>): void;
/** Forces the editor to update. Can be useful after adding a tokenize listener or modifying a grammar. */
update(this: void): void;
/** Gets `selectionStart`, `selectionEnd` and `selectionDirection` for the `textarea`. */
getSelection(this: void): InputSelection;
/** Adds a listener for events with the specified name. */
on<U extends keyof EditorEventMap>(this: void, name: U, listener: EditorEventMap<T>[U]): () => void;
/** Adds extensions to the editor and calls their update methods. */
addExtensions(this: void, ...extensions: EditorExtension<T>[]): void;
/** Removes the editor from the DOM. */
remove(this: void): void;
}