wed
Version:
Wed is a schema-aware editor for XML documents.
443 lines (363 loc) • 13.9 kB
TypeScript
/**
* The API presented to modes.
*
* @author Louis-Dominique Dubeau
* @license MPL 2.0
* @copyright Mangalam Research Center for Buddhist Languages
*/
import { Observable } from "rxjs";
import { Action } from "./action";
import { CaretManager } from "./caret-manager";
import { DLoc, DLocRange, DLocRoot } from "./dloc";
import * as domlistener from "./domlistener";
import { GUIUpdater } from "./gui-updater";
import { EditingMenuManager } from "./gui/editing-menu-manager";
import { Minibuffer } from "./gui/minibuffer";
import { Modal, Options as ModalOptions } from "./gui/modal";
import { Mode } from "./mode";
import { AttributeHidingSpecs } from "./mode-tree";
import { Options } from "./options";
import { Runtime } from "./runtime";
import { SelectionMode, SelectionModeChange } from "./selection-mode";
import { StockModals } from "./stock-modals";
import { Transformation, TransformationData,
TransformationEvent } from "./transformation";
import { TreeUpdater } from "./tree-updater";
import { UndoEvents, UndoMarker } from "./undo";
import { ModeValidator, Validator } from "./validator";
import { CleanedWedOptions } from "./wed-options-validation";
export interface PasteTransformationData extends TransformationData {
to_paste: Element;
}
export interface ReplaceRangeTransformationData extends TransformationData {
range: DLocRange;
newText: string;
caretAtEnd: boolean;
}
export interface CutUnitTransformationData extends TransformationData {
/** Whether to add to the clipboard or replace. */
add: boolean;
}
export interface DecoratorAPI {
/**
* This function adds a separator between each child element of the element
* passed as ``el``. The function only considers ``._real`` elements.
*
* @param el The element to decorate.
*
* @param sep A separator.
*/
listDecorator(el: Element, sep: string | Element): void;
/**
* Add a start label at the start of an element and an end label at the end.
*
* @param root The root of the decorated tree.
*
* @param el The element to decorate.
*
* @param level The level of the labels for this element.
*
* @param preContextHandler An event handler to run when the user invokes a
* context menu on the start label.
*
* @param postContextHandler An event handler to run when the user invokes a
* context menu on the end label.
*/
elementDecorator(root: Element, el: Element, level: number,
preContextHandler: ((wedEv: JQueryMouseEventObject,
ev: Event) => boolean) | undefined,
postContextHandler: ((wedEv: JQueryMouseEventObject,
ev: Event) => boolean) | undefined):
void;
}
export interface ModeTreeAPI {
/**
* Get the mode that governs a node.
*
* @param The node we want to check. This must be a done in the data tree or
* the GUI tree.
*
* @returns The mode that governs the node.
*/
getMode(node: Node): Mode;
/**
* Get the decorator that governs a node.
*/
getDecorator(node: Node): DecoratorAPI;
/**
* Get the processed wed options that are in effect for a given node.
*
* @param The node we want to check. This must be a done in the data tree or
* the GUI tree.
*
* @returns The wed options that governs the node.
*/
getWedOptions(node: Node): CleanedWedOptions;
/**
* Get the attribute handling that applies to a specific node.
*/
getAttributeHandling(node: Node): "show" | "hide" | "edit";
/**
* Get the attribute hiding specs that apply to a specific node.
*
* @returns The specifications that apply to the node. These specifications
* have been preprocessed to convert the selectors from being appropriate for
* the data tree to selectors appropriate for the GUI tree. ``null`` is
* returned if there are no specs.
*/
getAttributeHidingSpecs(node: Node): AttributeHidingSpecs | null;
/**
* Get the stylesheets that the modes define. It is up to the mode to use
* stylesheets that are written so as to avoid interfering with one another.
*
* @returns The list of sheets used by the modes. Straight duplicates are
* eliminated from the list. The paths must not require any further
* interpretation from wed.
*/
getStylesheets(): string[];
/**
* Get the maximum label visibility level configured by the modes. This
* function looks at all modes in use and returns the highest number it finds.
*
* @returns The maximum label visibility level.
*/
getMaxLabelLevel(): number;
/**
* Get the initial label visibility level configured by the modes. This
* function looks at all modes in use and returns the number that is set by
* the same mode used to provide the value of [[getMaxLabelLevel]].
*
* @returns The initial label visibility level.
*/
getInitialLabelLevel(): number;
/**
* @returns The list of all mode validators defined by the modes.
*/
getValidators(): ModeValidator[];
}
export interface EditorAPI {
/** A name for this editor. */
readonly name: string;
/** A promise that resolves once the first validation is complete. */
readonly firstValidationComplete: Promise<EditorAPI>;
/** A promise that resolves once the editor is initialized. */
readonly initialized: Promise<EditorAPI>;
/** The HTMLElement controlled by this editor */
readonly widget: HTMLElement;
/** Same as [[widget]] but as a jQuery object. */
readonly $widget: JQuery;
/** The <html> element that holds the widget. */
readonly $frame: JQuery;
/** The window which holds the widget. */
readonly window: Window;
/** The document which holds the widget. */
readonly doc: Document;
/** The runtime associated with this editor. */
readonly runtime: Runtime;
/** The options used by this editor. */
readonly options: Options;
/** The root of the GUI tree. */
readonly guiRoot: HTMLElement;
/** Same as [[guiRoot]] but as a jQuery object. */
readonly $guiRoot: JQuery;
/** The list of errors in the sidebar. */
readonly $errorList: JQuery;
/**
* The action to perform is a user is trying to do something with a complex
* pattern.
*/
readonly complexPatternAction: Action<{}>;
/** Paste transformation. */
readonly pasteTr: Transformation<PasteTransformationData>;
/** Paste unit transformation. */
readonly pasteUnitTr: Transformation<PasteTransformationData>;
/** Cut transformation. */
readonly cutTr: Transformation<TransformationData>;
/** Cut transformation. */
readonly cutUnitTr: Transformation<CutUnitTransformationData>;
/** Transformation for splitting nodes. */
readonly splitNodeTr: Transformation<TransformationData>;
/** Replace a range with text. */
readonly replaceRangeTr: Transformation<ReplaceRangeTransformationData>;
/** The minibuffer for this editor instance. */
readonly minibuffer: Minibuffer;
/** The URL for the embedded documentation page. */
readonly docURL: string;
/** The stream of transformation events for this editor. */
readonly transformations: Observable<TransformationEvent>;
/** The stream of selection mode changes for this editor. */
readonly selectionModeChanges: Observable<SelectionModeChange>;
/** The stream of undo/redo events for this editor. */
readonly undoEvents: Observable<UndoEvents>;
selectionMode: SelectionMode;
/** The root of the data tree. */
dataRoot: Document;
/** Same as [[dataRoot]] but as a jQuery object. */
$dataRoot: JQuery;
/** The maximum label level that labels may have. */
maxLabelLevel: number;
/** The [[DLocRoot]] object marking the root of the GUI tree. */
guiDLocRoot: DLocRoot;
/** The [[DLocRoot]] object marking the root of the data tree. */
dataDLocRoot: DLocRoot;
/** The updater through which all data tree manipulations must be made. */
dataUpdater: TreeUpdater;
/** The updater through which all GUI tree manipulations must be made. */
guiUpdater: GUIUpdater;
/** DOM listener on the GUI tree. */
domlistener: domlistener.DOMListener;
/** A collection of stock modals. */
modals: StockModals;
mergeWithPreviousHomogeneousSiblingTr: Transformation<TransformationData>;
mergeWithNextHomogeneousSiblingTr: Transformation<TransformationData>;
modeTree: ModeTreeAPI;
caretManager: CaretManager;
validator: Validator;
editingMenuManager: EditingMenuManager;
/**
* @param tr The transformation to fire.
*
* @param data Arbitrary data to be passed to the transformation.
*/
fireTransformation<T extends TransformationData>(tr: Transformation<T>,
data: T): void;
/**
* Record a marker into the list of undoable operations.
*
* We purposely restrict the objects that can be recored to
* [[UndoMarker]]. The editor does not support calling this method
* through the mode-api to record arbitrary [["undo".Undo]] objects.
*
* @param marker The marker to record.
*/
recordUndo(marker: UndoMarker): void;
/** Undo the last action recorded in the undo list. */
undo(): void;
/** Redo the previously undone action. */
redo(): void;
/**
* Determines whether an attribute is protected. A protected attribute cannot
* be deleted, added or edited by the user directly.
*
* @param attr The attribute to check. If it is an ``Element``, then it must
* be an ``_attribute_value`` element from the GUI tree. If it is an ``Attr``
* then it must be an attribute node from the data tree. If a string, then it
* must be the attribute name as it would appear in the data tree.
*
* @param parent If ``attr`` is a string, then ``parent`` must be set to the
* element for which the attribute would apply.
*
* @returns ``true`` if the attribute is protected.
*/
isAttrProtected(attr: string, parent: Element): boolean;
isAttrProtected(attr: Attr | Element): boolean;
/**
* Saves the document.
*
* @returns A promise that resolves when the save operation is done.
*/
save(): Promise<void>;
/**
* Inserts a transient placeholder. A transient placeholder is one that
* disappears if the caret is moved out of it.
*
* @param loc Location where to insert.
*
* @returns The placeholder.
*/
insertTransientPlaceholderAt(loc: DLoc): Element;
/** Find the data node that corresponds to a GUI node. */
toDataNode(node: Node): Node | Attr | null;
/** Find the GUI node that corresponds to a data node. */
fromDataNode(node: Node): Node | null;
/** Convert a GUI node to a node path. */
nodeToPath(node: Node | Attr): string;
/** Convert a node path to a GUI node. */
pathToNode(path: string): Node | Attr | null;
/**
* Get data associated with a mode.
*
* @param key An arbitrary key.
*
* @returns The data.
*/
// tslint:disable-next-line:no-any
getModeData(key: string): any;
/**
* Set the data associated with a mode. By convention the key should be a
* hierarchy of strings separated by dots. The first part should be the mode
* name. e.g. ``test-mode.actions.modal``.
*
* @param key An arbitrary key.
*
* @param value The value to record.
*/
// tslint:disable-next-line:no-any
setModeData(key: string, value: any): void;
/**
* Returns the list of element transformations for the location pointed to by
* the caret.
*
* @param treeCaret The location in the document. This must be a data
* location, not a GUI location.
*
* @param types The types of transformations to get.
*
* @return An array of objects having the fields ``tr`` which contain the
* actual transformation and ``name`` which is the unresolved element name for
* this transformation. It is exceptionally possible to have an item of the
* list contain ``undefined`` for ``name``.
*/
getElementTransformationsAt(treeCaret: DLoc, types: string | string[]):
{ tr: Action<{}>, name?: string }[];
/**
* Sets the list of items to show in the navigation list. This will make the
* list appear if it was not displayed previously.
*
* @param items The items to show.
*/
setNavigationList(items: Node | JQuery | Node[]): void;
/**
* Creates a tooltip for entities that are inside the GUI tree. All code that
* creates tooltips inside the GUI tree **must** use this method to create the
* tooltips. This accomplishes two goals:
*
* 1. The editor is able to perform cleanup operations on tooltips.
*
* 2. This method takes into account tooltips preferences. And thus will show
* or hide them depending on the preferences.
*
* @param $for The JQuery object for which we are creating a tooltip.
*
* @param options The tooltip options to use for this tooltip.
*/
makeGUITreeTooltip($for: JQuery, options: TooltipOptions): void;
makeModal(options?: ModalOptions): Modal;
/**
* Registers elements that are outside wed's editing pane but should be
* considered to be part of the editor. These would typically be menus or
* toolbars that a larger application that uses wed for editing adds around
* the editing pane.
*
* @param elements The elements to register.
*/
excludeFromBlur(elements: JQuery | Element): void;
/** Insert text at caret. */
insertText(text: string): void;
/** Whether the editor is in the midst of redoing or undoing. */
undoingOrRedoing(): boolean;
/**
* Decrease the label visibility level. It is a no-op if the level is already
* at the minimum.
*/
decreaseLabelVisiblityLevel(): void;
/**
* Increase the label visibility level. It is a no-op if the level is already
* at the maximum.
*/
increaseLabelVisibilityLevel(): void;
/**
* Toggle attribute hiding off and on.
*/
toggleAttributeHiding(): void;
}