wed
Version:
Wed is a schema-aware editor for XML documents.
389 lines (388 loc) • 15.3 kB
TypeScript
/// <reference types="jquery" />
/// <reference types="bootstrap" />
import "bootstrap";
import { Observable } from "rxjs";
import { Action } from "./action";
import { CaretManager } from "./caret-manager";
import { DLoc, DLocRoot } from "./dloc";
import * as domlistener from "./domlistener";
import * as editorActions from "./editor-actions";
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 { AddOptions, Toolbar } from "./gui/toolbar";
import { Key } from "./key";
import { CutUnitTransformationData, EditorAPI, PasteTransformationData, ReplaceRangeTransformationData } from "./mode-api";
import { ModeTree } from "./mode-tree";
import { Options } from "./options";
import { Runtime } from "./runtime";
import { Saver } from "./saver";
import { SelectionMode, SelectionModeChange } from "./selection-mode";
import { StockModals } from "./stock-modals";
import { Task, TaskRunner } from "./task-runner";
import { Transformation, TransformationData, TransformationEvent } from "./transformation";
import { TreeUpdater } from "./tree-updater";
import { Undo, UndoEvents } from "./undo";
import { Validator } from "./validator";
export declare const version = "4.0.0";
export declare type KeydownHandler = (wedEv: JQueryEventObject, ev: JQueryKeyEventObject) => boolean;
/**
* The possible targets for some wed operations that generate events. It is
* currently used to determine where to type keys when calling [[Editor.type]].
*/
export declare enum WedEventTarget {
/** The default target is the main editing panel. */
DEFAULT = 0,
/** Target the minibuffer. */
MINIBUFFER = 1,
}
/**
* This is the class to instantiate for editing.
*/
export declare class Editor implements EditorAPI {
private _firstValidationComplete;
private firstValidationCompleteResolve;
private initializedResolve;
private modeData;
private developmentMode;
private textUndoMaxLength;
private readonly taskRunners;
private taskSuspension;
private clipboardAdd;
private readonly normalizeEnteredSpaces;
private readonly strippedSpaces;
private readonly replacedSpaces;
private destroyed;
private initialLabelLevel;
private currentLabelLevel;
/** A temporary initialization value. */
private _dataChild;
private readonly scroller;
private readonly constrainer;
private readonly inputField;
private readonly $inputField;
private readonly clipboard;
private readonly caretLayer;
private readonly errorLayer;
private readonly wedLocationBar;
private readonly sidebar;
private readonly validationProgress;
private readonly validationMessage;
private readonly caretOwners;
private readonly clickedLabels;
private readonly withCaret;
private readonly $modificationStatus;
private readonly $saveStatus;
private readonly $navigationPanel;
private readonly $navigationList;
private readonly $excludedFromBlur;
private readonly errorItemHandlerBound;
private readonly appender;
private readonly _undo;
private readonly insertTextTr;
private readonly deleteCharTr;
private _selectionMode;
private undoRecorder;
private saveStatusInterval;
private readonly globalKeydownHandlers;
private updatingPlaceholder;
private readonly preferences;
private composing;
private compositionData;
private validationController;
private readonly _transformations;
private readonly _selectionModeChanges;
readonly name: string;
readonly firstValidationComplete: Promise<Editor>;
readonly initialized: Promise<Editor>;
readonly widget: HTMLElement;
readonly $widget: JQuery;
readonly $frame: JQuery;
readonly window: Window;
readonly doc: Document;
readonly runtime: Runtime;
readonly options: Options;
readonly guiRoot: HTMLElement;
readonly $guiRoot: JQuery;
readonly $errorList: JQuery;
readonly complexPatternAction: Action<{}>;
readonly pasteTr: Transformation<PasteTransformationData>;
readonly pasteUnitTr: Transformation<PasteTransformationData>;
readonly cutTr: Transformation<TransformationData>;
readonly cutUnitTr: Transformation<CutUnitTransformationData>;
readonly deleteSelectionTr: Transformation<TransformationData>;
readonly splitNodeTr: Transformation<TransformationData>;
readonly replaceRangeTr: Transformation<ReplaceRangeTransformationData>;
readonly removeMarkupTr: Transformation<TransformationData>;
readonly saveAction: Action<{}>;
readonly decreaseLabelVisibilityLevelAction: Action<{}>;
readonly increaseLabelVisibilityLevelAction: Action<{}>;
readonly undoAction: Action<{}>;
readonly redoAction: Action<{}>;
readonly toggleAttributeHidingAction: Action<{}>;
readonly setSelectionModeToSpan: Action<{}>;
readonly setSelectionModeToUnit: Action<{}>;
readonly minibuffer: Minibuffer;
readonly docURL: string;
readonly transformations: Observable<TransformationEvent>;
readonly selectionModeChanges: Observable<SelectionModeChange>;
readonly toolbar: Toolbar;
dataRoot: Document;
$dataRoot: JQuery;
maxLabelLevel: number;
guiDLocRoot: DLocRoot;
dataDLocRoot: DLocRoot;
dataUpdater: TreeUpdater;
guiUpdater: GUIUpdater;
domlistener: domlistener.DOMListener;
modals: StockModals;
mergeWithPreviousHomogeneousSiblingTr: Transformation<TransformationData>;
mergeWithNextHomogeneousSiblingTr: Transformation<TransformationData>;
modeTree: ModeTree;
caretManager: CaretManager;
validator: Validator;
editingMenuManager: EditingMenuManager;
saver: Saver;
constructor(widget: HTMLElement, options: Options | Runtime);
readonly undoEvents: Observable<UndoEvents>;
selectionMode: SelectionMode;
fireTransformation<T extends TransformationData>(tr: Transformation<T>, data: T): void;
private _fireTransformation<T>(tr, data);
/**
* Enter a state in which all tasks are suspended. It is possible to call this
* method while the state is already in effect. Its sister method
* ``exitTaskSuspension`` should be called the same number of times to resume
* the tasks.
*/
private enterTaskSuspension();
/**
* Exit a state in which all tasks are suspended. For the state to be
* effectively exited, this method needs to be called the same number of times
* ``enterTaskSuspension`` was called.
*/
private exitTaskSuspension();
/**
* Unconditionally stop all tasks.
*/
private stopAllTasks();
/**
* Unconditionally resume all tasks.
*/
private resumeAllTasks();
/**
* If we are not in the task suspended state that is entered upon calling
* ``enterTaskSuspension``, resume the task right away. Otherwise, this is a
* no-op.
*/
resumeTaskWhenPossible(task: TaskRunner): void;
/**
* Record an undo object in the list of undoable operations.
*
* Note that this method also provides the implementation for the restricted
* method of the same name that allows only [["wed/undo".UndoMarker]] objects.
*
* @param undo The object to record.
*/
recordUndo(undo: Undo): void;
undoAll(): void;
undo(): void;
redo(): void;
dumpUndo(): void;
undoingOrRedoing(): boolean;
isAttrProtected(attr: string, parent: Element): boolean;
isAttrProtected(attr: Attr | Element): boolean;
save(): Promise<void>;
private initiateTextUndo();
private terminateTextUndo();
private normalizeEnteredText(text);
private compensateForAdjacentSpaces(text, caret);
insertText(text: string): void;
private _insertText(_editor, data);
/**
* Delete a single character of text at caret.
*
* @param key The keyboard key that performs the deletion.
*
* @returns Whether a character was deleted.
*/
private deleteChar(key);
private _deleteChar(_editor, data);
private spliceAttribute(attrVal, offset, count, add);
insertTransientPlaceholderAt(loc: DLoc): Element;
toDataNode(node: Node): Node | Attr | null;
fromDataNode(node: Node): Node | null;
private onSaverSaved();
private onSaverAutosaved();
private onSaverChanged();
private onSaverFailed(event);
nodeToPath(node: Node | Attr): string;
pathToNode(path: string): Node | Attr | null;
getModeData(key: string): any;
setModeData(key: string, value: any): void;
destroy(): void;
init(xmlData?: string): Promise<Editor>;
private onModeChange(mode);
private postInitialize();
/**
* Handler preparing nodes included into the tree. This handler preforms an
* initial generic setup that does not need mode-specific information.
*/
private newContentHandler(ev);
private initializeNamespaces();
addToolbarAction(actionClass: editorActions.ActionCtor, options: AddOptions): void;
/**
* Creates a new task runner and registers it with the editor so that it is
* started and stopped by the methods that stop/start all tasks.
*
* @param task The task that the runner must run.
*
* @returns The new runner.
*/
newTaskRunner(task: Task): TaskRunner;
/**
* Triggers the resizing algorithm.
*/
resize(): void;
private resizeHandler();
/**
* Opens a documentation link.
*
* @param url The URL to open.
*/
openDocumentationLink(url: string): 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;
}[];
private shouldAddToClipboard();
private copyHandler(e);
private spanCopyHandler();
private notifyHeterogenousData();
private unitCopyHandler(add);
private cutHandler(e);
private spanCutHandler();
private unitCutHandler(add);
private cut(_editor, _data);
private cutUnit(_editor, data);
private pasteHandler(e);
private clipboardToElement(data);
private spanPasteHandler(e);
private unitPasteHandler(e);
private pasteIntoElement(caret, toPaste);
private paste(_editor, data);
private pasteUnit(_editor, data);
private keydownHandler(e);
pushGlobalKeydownHandler(handler: KeydownHandler): void;
popGlobalKeydownHandler(handler: KeydownHandler): void;
private globalKeydownHandler(wedEvent, e);
private keypressHandler(e);
/**
* Simulates typing text in the editor.
*
* **NOTE**: this function is limited in what it can simulate. The main
* editing pane is where you get the most support. Other locations offer less
* support. One good example is the minibuffer. Typing a string into it works
* fine. Trying to use directional arrows and backspace/delete currently does
* not work. We'd have to write custom code to handle these cases because it
* is not possible, as we speak, to write JavaScript code that **entirely**
* simulates pressing keyboard keys. (JavaScript easily supports sending the
* events *generated* by hitting the keyboard, but this is not enough.)
*
* @param text The text to type in. An array of keys, a string or a single
* key.
*/
type(text: string | Key | Key[], where?: WedEventTarget): void;
private globalKeypressHandler(_wedEvent, e);
/**
* Delete the current selection from the document. If the selection is not
* well-formed, this is a no-op.
*
* We do not call this a "cut" because a real cut operation modifies the
* clipboard. Whereas this does not.
*
* @returns ``false`` if there was no selection to process, or the selection
* was empty. ``true`` otherwise.
*/
private deleteSelection();
private _deleteSelection(_editor, _data);
private handleKeyInsertingText(e);
private compositionHandler(ev);
private inputHandler();
private mousemoveHandler(e);
private mousedownHandler(ev);
private mouseupHandler(ev);
private mouseoverHandler(ev);
private mouseoutHandler(ev);
private refreshSaveStatus();
private onValidatorStateChange(workingState);
private onPossibleDueToWildcardChange(node);
/**
* Expand the error panel if there is no navigation.
*/
expandErrorPanelWhenNoNavigation(): void;
private errorItemHandler(ev);
setNavigationList(items: Node | JQuery | Node[]): void;
makeModal(options?: ModalOptions): Modal;
makeGUITreeTooltip($for: JQuery, options: TooltipOptions): void;
/**
* Reset the label visibility level to what it was when the editor was first
* initialized.
*/
resetLabelVisibilityLevel(): void;
/**
* Set the visibility level to a specific value. It is a no-op if it is called
* with a value that is less than 0 or greater than the maximum level
* supported, or if the new level is the same as the current level.
*
* @param level The new level.
*/
setLabelVisibilityLevel(level: number): void;
increaseLabelVisibilityLevel(): void;
decreaseLabelVisiblityLevel(): void;
toggleAttributeHiding(): void;
private closeAllTooltips();
excludeFromBlur(elements: JQuery | Element): void;
/**
* Finds the location of the character closest to the ``x, y``
* coordinates. Very often this will be the character whose bounding client
* rect encloses the coordinates. However, if no such character exists the
* algorithm will return the closest character. If multiple characters are at
* the same distance, then the first one found will be returned.
*
* @param x The x coordinate in client coordinates.
*
* @param y The y coordinate in client coordinates.
*
* @returns The location of the boundary character. The value return is
* ``undefined`` if the coordinates are outside the client or if the element
* in which the click occurred is not inside the editor pane (a descendant of
* ``this.guiRoot``).
*/
private findLocationAt(x, y);
private findLocationInElementAt(node, x, y, textOk?);
private pointToCharBoundary(x, y);
private caretChange(ev);
/**
* Set the location bar to a new location.
*
* @param el The element at which the location should point.
*/
private setLocationTo(el);
replaceRange(editor: EditorAPI, data: ReplaceRangeTransformationData): void;
}
export { PasteTransformationData, ReplaceRangeTransformationData };