UNPKG

wed

Version:

Wed is a schema-aware editor for XML documents.

318 lines (317 loc) 12.9 kB
import { Subject } from "rxjs"; import { Action } from "./action"; import { DLoc } from "./dloc"; import { EditorAPI } from "./mode-api"; import { TreeUpdater } from "./tree-updater"; /** * Data passed to the transformation handler. The transformation types expect * the following values for the parameters passed to a handler. * * Transformation Type | `node` is | `name` is the name of the: * --------------------|-----------|--------------------------- * insert | undefined (we insert at caret position) | element to insert * delete-element | element to delete | element to delete * delete-parent | element to delete | element to delete * wrap | undefined (we wrap the current selection) | wrapping element * merge-with-next | element to merge | element to merge * merge-with-previous | element to merge | element to merge * swap-with-next | element to swap | element to swap * swap-with-previous | element to swap | element to swap * append | element after which to append | element after which to append * prepend | element before which to prepend | element before which to append * unwrap | node to unwrap | node to unwrap * add-attribute | node to which an attribute is added | attribute to add * delete-attribute | attribute to delete | attribute to delete * insert-text | node to which text is added | text to add */ export interface TransformationData { /** * The JavaScript event that triggered the transformation, if any. */ readonly e?: Event; /** * The node to operate on. Should be set by the code that invokes the * transformation. This may be undefined if the transformation should rely on * the caret position. */ node?: Node; /** * The name of the node to add, remove, etc. Should be set by the code that * invokes the transformation. */ name?: string; /** * A position to which the caret is moved before the transformation is fired. * **Wed performs the move.** Should be set by the code that invokes the * transformation. */ moveCaretTo?: DLoc; } export interface NamedTransformationData extends TransformationData { name: string; } /** * @param editor The editor. * * @param data The data for the transformation. */ export declare type TransformationHandler<Data extends TransformationData> = (editor: EditorAPI, data: Data) => void; export interface TransformationOptions { /** An abbreviated description of this transformation. */ abbreviatedDesc?: string; /** An HTML representation of the icon associated with this transformation. */ iconHtml?: string; /** * Indicates whether this action needs input from the user. For instance, an * action which brings up a modal dialog to ask something of the user must * have this parameter set to ``true``. It is important to record whether an * action needs input because, to take one example, the ``autoinsert`` logic * will try to insert automatically any element it can. However, doing this * for elements that need user input will just confuse the user (or could * cause a crash). Therefore, it is important that the insertion operations * for such elements be marked with ``needsInput`` set to ``true`` so that the * ``autoinsert`` logic backs off from trying to insert these elements. * * Defaults to ``false`` if not specified. */ needsInput?: boolean; /** * Indicates whether this transformation needs to be treated as a kind of text * input. * * The distinction originates with how typing text is treated differently for * undo/redo purposes than other changes to a document. We group sequences of * keys together, with a default maximum length of 10 keys. So if I type * ``abcdefghijklmn`` and then undo. The ``klmn`` will be removed and then if * I do another undo the rest of the text will be undone. The first ten * characters were grouped in an undo group, and the last four in another. * * Some key presses can trigger transformations, and such transformations need * to be treated as text input. */ treatAsTextInput?: boolean; } /** * An operation that transforms the data tree. */ export declare class Transformation<Data extends TransformationData, Handler extends TransformationHandler<Data> = TransformationHandler<Data>> extends Action<Data> { readonly handler: Handler; readonly transformationType: string; readonly kind: string; readonly nodeType: string; readonly treatAsTextInput: boolean; /** * @param editor The editor for which this transformation is created. * * @param transformationType The type of transformation. * * @param desc The description of this transformation. A transformation's * [[getDescriptionFor]] method will replace ``<name>`` with the name of the * node actually being processed. So a string like ``Remove <name>`` would * become ``Remove foo`` when the transformation is called for the element * ``foo``. * * @param handler The handler to call when this transformation is executed. * * @param options Additional options. */ constructor(editor: EditorAPI, transformationType: string, desc: string, handler: Handler, options?: TransformationOptions); getDescriptionFor(data: Data): string; /** * Calls the ``fireTransformation`` method on this transformation's editor. * * @param data The data object to pass. */ execute(data: Data): void; } /** * Transformation events are generated by an editor before and after a * transformation is executed. The ``StartTransformation`` event is generated * before, and the ``EndTransformation`` is generated after. These events allow * modes to perform additional processing before or after a transformation, or * to abort a transformation while it is being processed. */ export declare class TransformationEvent { readonly name: "StartTransformation" | "EndTransformation"; readonly transformation: Transformation<TransformationData>; private _aborted; private _abortMessage?; /** * @param name The name of the event. * @param transformation The transformation to which the event pertains. */ constructor(name: "StartTransformation" | "EndTransformation", transformation: Transformation<TransformationData>); /** Whether the transformation is aborted. */ readonly aborted: boolean; /** * Mark the transformation as aborted. Once aborted, a transformation cannot * be unaborted. */ abort(message: string): void; /** * Raise an [[AbortTransformationException]] if the event was marked as * aborted. */ throwIfAborted(): void; } /** * A subject that emits [[TransformationEvent]] objects and immediately stops * calling subscribers when the [[TransformationEvent]] object it is processing * is aborted. */ export declare class TransformationEventSubject extends Subject<TransformationEvent> { next(value: TransformationEvent): void; } export declare type AttributeTable = Record<string, string>; /** * Makes an element appropriate for a wed data tree. * * @param doc The document for which to make the element. * * @param ns The URI of the namespace to use for the new element. * * @param name The name of the new element. * * @param attrs An object whose fields will become attributes for the new * element. * * @returns The new element. */ export declare function makeElement(doc: Document, ns: string, name: string, attrs?: AttributeTable): Element; /** * Insert an element in a wed data tree. * * @param dataUpdater A tree updater through which to update the DOM tree. * * @param parent The parent of the new node. * * @param index Offset in the parent where to insert the new node. * * @param ns The URI of the namespace to use for the new element. * * @param name The name of the new element. * * @param attrs An object whose fields will become attributes for the new * element. * * @returns The new element. */ export declare function insertElement(dataUpdater: TreeUpdater, parent: Node, index: number, ns: string, name: string, attrs?: AttributeTable): Element; /** * Wraps a span of text in a new element. * * @param dataUpdater A tree updater through which to update the DOM tree. * * @param node The DOM node where to wrap. Must be a text node. * * @param offset The offset in the node. This parameter specifies where to start * wrapping. * * @param endOffset Offset in the node. This parameter specifies where to end * wrapping. * * @param ns The URI of the namespace to use for the new element. * * @param name The name of the wrapping element. * * @param attrs An object whose fields will become attributes for the new * element. * * @returns The new element. */ export declare function wrapTextInElement(dataUpdater: TreeUpdater, node: Text, offset: number, endOffset: number, ns: string, name: string, attrs?: AttributeTable): Element; /** * Wraps a well-formed span in a new element. This span can contain text and * element nodes. * * @param dataUpdater A tree updater through which to update the DOM tree. * * @param startContainer The node where to start wrapping. * * @param startOffset The offset where to start wrapping. * * @param endContainer The node where to end wrapping. * * @param endOffset The offset where to end wrapping. * * @param ns The URI of the namespace to use for the new element. * * @param name The name of the new element. * * @param [attrs] An object whose fields will become attributes for the new * element. * * @returns The new element. * * @throws {Error} If the range is malformed or if there is an internal error. */ export declare function wrapInElement(dataUpdater: TreeUpdater, startContainer: Node, startOffset: number, endContainer: Node, endOffset: number, ns: string, name: string, attrs?: AttributeTable): Element; /** * Replaces an element with its contents. * * @param dataUpdater A tree updater through which to update the DOM tree. * * @param node The element to unwrap. * * @returns The contents of the element. */ export declare function unwrap(dataUpdater: TreeUpdater, node: Element): Node[]; /** * This function splits a node at the position of the caret. If the caret is not * inside the node or its descendants, an exception is raised. * * @param editor The editor on which we are to perform the transformation. * * @param node The node to split. * * @throws {Error} If the caret is not inside the node or its descendants. */ export declare function splitNode(editor: EditorAPI, node: Node): void; /** * This function merges an element with a previous element of the same name. For * the operation to go forward, the element must have a previous sibling and * this sibling must have the same name as the element being merged. * * @param editor The editor on which we are to perform the transformation. * * @param node The element to merge with previous. */ export declare function mergeWithPreviousHomogeneousSibling(editor: EditorAPI, node: Element): void; /** * This function merges an element with a next element of the same name. For the * operation to go forward, the element must have a next sibling and this * sibling must have the same name as the element being merged. * * @param editor The editor on which we are to perform the transformation. * * @param node The element to merge with next. */ export declare function mergeWithNextHomogeneousSibling(editor: EditorAPI, node: Element): void; /** * This function swaps an element with a previous element of the same name. For * the operation to go forward, the element must have a previous sibling and * this sibling must have the same name as the element being merged. * * @param editor The editor on which we are to perform the transformation. * * @param node The element to swap with previous. */ export declare function swapWithPreviousHomogeneousSibling(editor: EditorAPI, node: Element): void; /** * This function swaps an element with a next element of the same name. For the * operation to go forward, the element must have a next sibling and this * sibling must have the same name as the element being merged. * * @param editor The editor on which we are to perform the transformation. * * @param node The element to swap with next. */ export declare function swapWithNextHomogeneousSibling(editor: EditorAPI, node: Element): void; /** * Remove markup from the current selection. This turns mixed content into pure * text. The selection must be well-formed, otherwise the transformation is * aborted. * * @param editor The editor for which we are doing the transformation. */ export declare function removeMarkup(editor: EditorAPI): void;