From b5a2f5e5d3d4cc0c7b134ff99020255d6bcec4dd Mon Sep 17 00:00:00 2001 From: mkslanc Date: Wed, 23 Oct 2024 14:56:39 +0400 Subject: [PATCH] improve types for internal development --- ace-internal.d.ts | 262 +++++++++++++++++++--------------- src/ace.js | 5 +- src/anchor.js | 7 +- src/autocomplete.js | 71 ++++++---- src/bidihandler.js | 28 ++-- src/config.js | 16 +-- src/edit_session.js | 80 ++++++----- src/editor.js | 179 ++++++++++++++--------- src/ext/code_lens.js | 10 +- src/ext/searchbox.js | 30 ++-- src/ext/static_highlight.js | 33 +++-- src/incremental_search.js | 6 +- src/keyboard/keybinding.js | 14 +- src/lib/app_config.js | 6 +- src/lib/lang.js | 13 +- src/line_widgets.js | 65 ++++----- src/marker_group.js | 8 +- src/mode/behaviour.js | 6 +- src/mode/behaviour/css.js | 1 + src/mode/behaviour/cstyle.js | 19 ++- src/mode/behaviour/html.js | 1 + src/mode/behaviour/liquid.js | 1 + src/mode/behaviour/xml.js | 3 +- src/mode/behaviour/xquery.js | 7 +- src/mode/text.js | 34 +++-- src/mouse/mouse_handler.js | 8 +- src/multi_select.js | 52 +++---- src/placeholder.js | 34 ++--- src/scrollbar.js | 14 +- src/scrollbar_custom.js | 8 +- src/search.js | 66 ++++----- src/snippets.js | 69 +++++---- src/tooltip.js | 46 +++--- src/virtual_renderer.js | 268 ++++++++++++++++++----------------- 34 files changed, 808 insertions(+), 662 deletions(-) diff --git a/ace-internal.d.ts b/ace-internal.d.ts index 7a345ea0828..96d51a66eb3 100644 --- a/ace-internal.d.ts +++ b/ace-internal.d.ts @@ -26,38 +26,22 @@ export namespace Ace { type GutterHandler = import("./src/mouse/default_gutter_handler").GutterHandler; type DragdropHandler = import("./src/mouse/dragdrop_handler").DragdropHandler; type AppConfig = import("./src/lib/app_config").AppConfig; - + type Config = typeof import("./src/config"); type AfterLoadCallback = (err: Error | null, module: unknown) => void; type LoaderFunction = (moduleName: string, afterLoad: AfterLoadCallback) => void; - export interface Config { - get(key: string): any; - - set(key: string, value: any): void; - - all(): { [key: string]: any }; - - moduleUrl(name: string, component?: string): string; - - setModuleUrl(name: string, subst: string): string; - - setLoader(cb: LoaderFunction): void; - - setModuleLoader(name: string, onLoad: Function): void; - - loadModule(moduleName: string | [string, string], - onLoad?: (module: any) => void): void; - - init(packaged: any): any; - - defineOptions(obj: any, path: string, options: { [key: string]: any }): Config; - - resetOptions(obj: any): void; - - setDefaultValue(path: string, name: string, value: any): void; - - setDefaultValues(path: string, optionHash: { [key: string]: any }): void; + export interface ConfigOptions { + packaged: boolean, + workerPath: string | null, + modePath: string | null, + themePath: string | null, + basePath: string, + suffix: string, + $moduleUrls: { [url: string]: string }, + loadWorkerFromBlob: boolean, + sharedPopups: boolean, + useStrictCSP: boolean | null } interface Theme { @@ -364,7 +348,7 @@ export namespace Ace { highlightGutterLine: boolean; hScrollBarAlwaysVisible: boolean; vScrollBarAlwaysVisible: boolean; - fontSize: string; + fontSize: string | number; fontFamily: string; maxLines: number; minLines: number; @@ -414,6 +398,7 @@ export namespace Ace { enableMultiselect: boolean; enableKeyboardAccessibility: boolean; enableCodeLens: boolean; + textInputAriaLabel: string; enableMobileMenu: boolean; } @@ -427,15 +412,10 @@ export namespace Ace { * @param delta */ "change": (delta: Delta) => void; - /** - * Emitted when the selection changes. - */ - "changeSelection": () => void; /** * Emitted when the tab size changes, via [[EditSession.setTabSize]]. - * @param tabSize */ - "changeTabSize": (tabSize: number) => void; + "changeTabSize": () => void; /** * Emitted when the ability to overwrite text changes, via [[EditSession.setOverwrite]]. * @param overwrite @@ -445,46 +425,43 @@ export namespace Ace { * Emitted when the gutter changes, either by setting or removing breakpoints, or when the gutter decorations change. * @param e */ - "changeBreakpoint": (e: { row: number, breakpoint: boolean }) => void; + "changeBreakpoint": (e?: { row?: number, breakpoint?: boolean }) => void; /** * Emitted when a front marker changes. - * @param e */ - "changeFrontMarker": (e: { row: number, marker: boolean }) => void; + "changeFrontMarker": () => void; /** * Emitted when a back marker changes. - * @param e */ - "changeBackMarker": (e: { row: number, marker: boolean }) => void; + "changeBackMarker": () => void; /** * Emitted when an annotation changes, like through [[EditSession.setAnnotations]]. - * @param e */ - "changeAnnotation": (e: { row: number, lines: string[] }) => void; + "changeAnnotation": (e: {}) => void; /** * Emitted when a background tokenizer asynchronously processes new rows. */ - "tokenizerUpdate": (e: { data: { first: string, last: string } }) => void; + "tokenizerUpdate": (e: { data: { first: number, last: number } }) => void; /** * Emitted when the current mode changes. * @param e */ - "changeMode": (e) => void; + "changeMode": (e: any) => void; /** * Emitted when the wrap mode changes. * @param e */ - "changeWrapMode": (e) => void; + "changeWrapMode": (e: any) => void; /** * Emitted when the wrapping limit changes. * @param e */ - "changeWrapLimit": (e) => void; + "changeWrapLimit": (e: any) => void; /** * Emitted when a code fold is added or removed. * @param e */ - "changeFold": (e, session: EditSession) => void; + "changeFold": (e: any, session?: EditSession) => void; /** * Emitted when the scroll top changes. * @param scrollTop The new scroll top value @@ -495,17 +472,11 @@ export namespace Ace { * @param scrollLeft The new scroll left value **/ "changeScrollLeft": (scrollLeft: number) => void; - "changeEditor": (e: { editor: Editor }) => void; - /** - * Emitted after operation starts. - * @param commandEvent event causing the operation - */ - "startOperation": (commandEvent) => void; - /** - * Emitted after operation finishes. - * @param e event causing the finish - */ - "endOperation": (e) => void; + "changeEditor": (e: { editor?: Editor, oldEditor?: Editor }) => void; + "changeSelection": () => void; + "startOperation": (op?: { command?: { name?: string }, args?: any }) => void; + "endOperation": (op?: any) => void; + "beforeEndOperation": () => void; } interface EditorEvents { @@ -517,31 +488,40 @@ export namespace Ace { * @param e An object with two properties, `oldSession` and `session`, that represent the old and new [[EditSession]]s. **/ "changeSession": (e: { oldSession: EditSession, session: EditSession }) => void; - "blur": (e) => void; + "blur": (e: any) => void; "mousedown": (e: MouseEvent) => void; - "mousemove": (e: MouseEvent & { scrollTop? }, editor?: Editor) => void; - "changeStatus": () => void; - "keyboardActivity": () => void; + "mousemove": (e: MouseEvent & { scrollTop?: any }, editor?: Editor) => void; + "changeStatus": (e: any) => void; + "keyboardActivity": (e: any) => void; "mousewheel": (e: MouseEvent) => void; "mouseup": (e: MouseEvent) => void; - "beforeEndOperation": (e) => void; - "nativecontextmenu": (e) => void; - "destroy": () => void; - "focus": () => void; + "beforeEndOperation": (e: any) => void; + "nativecontextmenu": (e: any) => void; + "destroy": (e: any) => void; + "focus": (e?: any) => void; /** * Emitted when text is copied. * @param text The copied text **/ - "copy": (text: string) => void; + "copy": (e: { text: string }) => void; /** * Emitted when text is pasted. **/ - "paste": (text: string, event) => void; + "paste": (text: string, event: any) => void; /** * Emitted when the selection style changes, via [[Editor.setSelectionStyle]]. * @param data Contains one property, `data`, which indicates the new selection style **/ "changeSelectionStyle": (data: "fullLine" | "screenLine" | "text" | "line") => void; + "changeMode": (e: { mode?: Ace.SyntaxMode, oldMode?: Ace.SyntaxMode }) => void; + + //from searchbox extension + "findSearchBox": (e: { match: boolean }) => void; + + //from code_lens extension + "codeLensClick": (e: any) => void; + + "select": () => void; } interface AcePopupEvents { @@ -552,7 +532,7 @@ export namespace Ace { "show": () => void; "hide": () => void; "select": (hide: boolean) => void; - "changeHoverMarker": (e) => void; + "changeHoverMarker": (e: any) => void; } interface DocumentEvents { @@ -586,9 +566,11 @@ export namespace Ace { interface BackgroundTokenizerEvents { /** * Fires whenever the background tokeniziers between a range of rows are going to be updated. - * @param {Object} e An object containing two properties, `first` and `last`, which indicate the rows of the region being updated. + * @param e An object containing two properties, `first` and `last`, which indicate the rows of the region being updated. **/ - "update": (e: { first: number, last: number }) => void; + "update": (e: { + data: { first: number, last: number } + }) => void; } interface SelectionEvents { @@ -602,21 +584,36 @@ export namespace Ace { "changeSelection": () => void; } - interface PlaceHolderEvents { + interface MultiSelectionEvents extends SelectionEvents { + "multiSelect": () => void; + "addRange": (e: { range: Range }) => void; + "removeRange": (e: { ranges: Range[] }) => void; + "singleSelect": () => void; + } + interface PlaceHolderEvents { + "cursorEnter": (e: any) => void; + "cursorLeave": (e: any) => void; } interface GutterEvents { "changeGutterWidth": (width: number) => void; + "afterRender": () => void; } interface TextEvents { - "changeCharacterSize": (e) => void; + "changeCharacterSize": (e: any) => void; } interface VirtualRendererEvents { - "afterRender": (e, renderer: VirtualRenderer) => void; - "beforeRender": (e, renderer: VirtualRenderer) => void; + "afterRender": (e?: any, renderer?: VirtualRenderer) => void; + "beforeRender": (e: any, renderer?: VirtualRenderer) => void; + "themeLoaded": (e: { theme: string | Theme }) => void; + "themeChange": (e: { theme: string | Theme }) => void; + "scrollbarVisibilityChanged": () => void; + "changeCharacterSize": (e: any) => void; + "resize": (e?: any) => void; + "autosize": () => void; } class EventEmitter { @@ -638,26 +635,42 @@ export namespace Ace { removeAllListeners(name?: string): void; - _signal(eventName: string, e: any): void; + _signal(eventName: K, ...args: Parameters): void; - _emit(eventName: string, e: any): void; + _emit(eventName: K, ...args: Parameters): void; - _dispatchEvent(eventName: string, e: any): void; + _dispatchEvent(eventName: K, ...args: Parameters): void; } interface SearchOptions { + /**The string or regular expression you're looking for*/ needle: string | RegExp; preventScroll: boolean; + /**Whether to search backwards from where cursor currently is*/ backwards: boolean; + /**The starting [[Range]] or cursor position to begin the search*/ start: Range; + /**Whether or not to include the current line in the search*/ skipCurrent: boolean; - range: Range; + /**The [[Range]] to search within. Set this to `null` for the whole document*/ + range: Range | null; preserveCase: boolean; + /**Whether the search is a regular expression or not*/ regExp: boolean; + /**Whether the search matches only on whole words*/ wholeWord: boolean; + /**Whether the search ought to be case-sensitive*/ caseSensitive: boolean; + /**Whether to wrap the search back to the beginning when it hits the end*/ wrap: boolean; - re: RegExp; + re: any; + /**true, if needle has \n or \r\n*/ + $isMultiLine: boolean; + /** + * internal property, determine if browser supports unicode flag + * @private + * */ + $supportsUnicodeFlag: boolean; } interface Point { @@ -711,7 +724,7 @@ export namespace Ace { type KeyboardHandler = Partial & { attach?: (editor: Editor) => void; detach?: (editor: Editor) => void; - getStatusText?: (editor?: any, data?) => string; + getStatusText?: (editor?: any, data?: any) => string; } export interface MarkerLike { @@ -805,6 +818,8 @@ export namespace Ace { type BehaviorMap = Record>; interface Behaviour { + $behaviours: { [behaviour: string]: any } + add(name: string, action: string, callback: BehaviorAction): void; addBehaviours(behaviours: BehaviorMap): void; @@ -891,7 +906,7 @@ export namespace Ace { $createKeywordList(): string[]; - $delegator(method: string, args: IArguments, defaultHandler): any; + $delegator(method: string, args: IArguments, defaultHandler: any): any; } @@ -943,7 +958,7 @@ export namespace Ace { interface TextInput { resetSelection(): void; - setAriaOption(options?: { activeDescendant: string, role: string, setLabel }): void; + setAriaOption(options?: { activeDescendant: string, role: string, setLabel: any }): void; } type CompleterCallback = (error: any, completions: Completion[]) => void; @@ -958,13 +973,16 @@ export namespace Ace { callback: CompleterCallback): void; getDocTooltip?(item: Completion): void | string | Completion; + onSeen?: (editor: Ace.Editor, completion: Completion) => void; onInsert?: (editor: Ace.Editor, completion: Completion) => void; + cancel?(): void; id?: string; triggerCharacters?: string[]; hideInlinePreview?: boolean; + insertMatch?: (editor: Editor, data: Completion) => void; } interface CompletionOptions { @@ -997,18 +1015,18 @@ export namespace Ace { * Adds the selection and cursor. * @param orientedRange A range containing a cursor **/ - addSelectionMarker: (orientedRange: Ace.Range & { marker? }) => Ace.Range & { marker? }, + addSelectionMarker: (orientedRange: Ace.Range & { marker?: any }) => Ace.Range & { marker?: any }, /** * Removes the selection marker. * @param range The selection range added with [[Editor.addSelectionMarker `addSelectionMarker()`]]. **/ - removeSelectionMarker: (range: Ace.Range & { marker? }) => void, - removeSelectionMarkers: (ranges: (Ace.Range & { marker? })[]) => void, - $onAddRange: (e) => void, - $onRemoveRange: (e) => void, - $onMultiSelect: (e) => void, - $onSingleSelect: (e) => void, - $onMultiSelectExec: (e) => void, + removeSelectionMarker: (range: Ace.Range & { marker?: any }) => void, + removeSelectionMarkers: (ranges: (Ace.Range & { marker?: any })[]) => void, + $onAddRange: (e: any) => void, + $onRemoveRange: (e: any) => void, + $onMultiSelect: (e: any) => void, + $onSingleSelect: (e: any) => void, + $onMultiSelectExec: (e: any) => void, /** * Executes a command for each selection range. * @param cmd The command to execute @@ -1020,7 +1038,7 @@ export namespace Ace { **/ exitMultiSelectMode: () => void, getSelectedText: () => string, - $checkMultiselectChange: (e, anchor: Ace.Anchor) => void, + $checkMultiselectChange: (e: any, anchor: Ace.Anchor) => void, /** * Finds and selects all the occurrences of `needle`. * @param needle The text to find @@ -1057,8 +1075,17 @@ export namespace Ace { $blockSelectEnabled?: boolean, } + interface CodeLenseProvider { + provideCodeLenses: (session: EditSession, callback: (err: any, payload: CodeLense[]) => void) => void; + } + + interface CodeLense { + start: Point, + command: any + } + interface CodeLenseEditorExtension { - codeLensProviders?: any[]; + codeLensProviders?: CodeLenseProvider[]; $codeLensClickHandler?: any; $updateLenses?: () => void; $updateLensesOnInput?: () => void; @@ -1168,7 +1195,7 @@ export namespace Ace { type TooltipCommandFunction = (editor: Ace.Editor) => T; export interface TooltipCommand extends Ace.Command { - enabled: TooltipCommandFunction | boolean, + enabled?: TooltipCommandFunction | boolean, getValue?: TooltipCommandFunction, type: "button" | "text" | "checkbox" iconCssClass?: string, @@ -1181,6 +1208,14 @@ export namespace Ace { className?: string, value: string, }>> + + export interface StaticHighlightOptions { + mode?: string | SyntaxMode, + theme?: string | Theme, + trim?: boolean, + firstLineNumber?: number, + showGutter?: boolean + } } @@ -1189,10 +1224,10 @@ export const config: Ace.Config; export function require(name: string): any; -export function edit(el: string | (Element & { - env?; - value?; -}), options?: Partial): Ace.Editor; +export function edit(el?: string | (Element & { + env?: any; + value?: any; +}) | null, options?: Partial): Ace.Editor; export function createEditSession(text: Ace.Document | string, mode: Ace.SyntaxMode): Ace.EditSession; @@ -1220,6 +1255,7 @@ export type CommandBarTooltip = Ace.CommandBarTooltip; declare global { interface Element { setAttribute(name: string, value: boolean): void; + setAttribute(name: string, value: number): void; } } @@ -1252,7 +1288,6 @@ declare module "./src/background_tokenizer" { declare module "./src/document" { export interface Document extends Ace.EventEmitter { - } } @@ -1301,12 +1336,6 @@ declare module "./src/edit_session" { widgetManager?: any, $bracketHighlight?: any, $selectionMarker?: number, - curOp?: { - command: {}, - args: string, - scrollTop: number, - [key: string]: any; - }, lineWidgetsWidth?: number, $getWidgetScreenLength?: () => number, _changedWidgets?: any, @@ -1315,9 +1344,6 @@ declare module "./src/edit_session" { $enableVarChar?: any, $wrap?: any, $navigateWithinSoftTabs?: boolean, - - getSelectionMarkers(): any[], - $selectionMarkers?: any[], gutterRenderer?: any, $firstLineNumber?: number, @@ -1329,6 +1355,14 @@ declare module "./src/edit_session" { $occurMatchingLines?: any, $useEmacsStyleLineStart?: boolean, $selectLongWords?: boolean, + curOp?: { + command: {}, + args: string, + scrollTop: number, + [key: string]: any; + }, + + getSelectionMarkers(): any[], } } @@ -1369,9 +1403,8 @@ declare module "./src/line_widgets" { } declare module "./src/selection" { - export interface Selection extends Ace.EventEmitter, Ace.MultiSelectProperties { + export interface Selection extends Ace.EventEmitter, Ace.MultiSelectProperties { } - } declare module "./src/range" { @@ -1397,7 +1430,6 @@ declare module "./src/virtual_renderer" { $maxLines?: number, $scrollPastEnd?: number, enableKeyboardAccessibility?: boolean, - keyboardFocusClassName?: string, $highlightGutterLine?: boolean, $minLines?: number, $maxPixelHeight?: number, @@ -1410,12 +1442,13 @@ declare module "./src/virtual_renderer" { $theme?: any, destroyed?: boolean, session: Ace.EditSession, + keyboardFocusClassName?: string, } } declare module "./src/snippets" { - export interface SnippetManager extends Ace.EventEmitter { + interface SnippetManager extends Ace.EventEmitter { } } @@ -1526,3 +1559,8 @@ declare module "./src/mouse/default_gutter_handler" { export interface GutterHandler { } } + +declare module "./src/lib/keys" { + export function keyCodeToString(keyCode: number): string; +} + diff --git a/src/ace.js b/src/ace.js index 86ea484a156..2e2180fdd5a 100644 --- a/src/ace.js +++ b/src/ace.js @@ -28,7 +28,7 @@ exports.config = require("./config"); /** * Embeds the Ace editor into the DOM, at the element provided by `el`. - * @param {String | HTMLElement & {env?, value?}} el Either the id of an element, or the element itself + * @param {String | HTMLElement & {env?: any, value?: any} | null} [el] Either the id of an element, or the element itself * @param {Object } [options] Options for the editor * @returns {Editor} **/ @@ -86,4 +86,5 @@ exports.Editor = Editor; exports.EditSession = EditSession; exports.UndoManager = UndoManager; exports.VirtualRenderer = Renderer; -exports.version = exports.config.version; +var version = exports.config.version; +exports.version = version; diff --git a/src/anchor.js b/src/anchor.js index b5d112c9a6d..4959ec1fa0e 100644 --- a/src/anchor.js +++ b/src/anchor.js @@ -25,7 +25,7 @@ class Anchor { else this.setPosition(row, column); } - + /** * Returns an object identifying the `row` and `column` position of the current anchor. * @returns {import("../ace-internal").Ace.Point} @@ -42,10 +42,11 @@ class Anchor { getDocument() { return this.document; } - + /** * Internal function called when `"change"` event fired. * @param {import("../ace-internal").Ace.Delta} delta + * @internal */ onChange(delta) { if (delta.start.row == delta.end.row && delta.start.row != this.row) @@ -53,7 +54,7 @@ class Anchor { if (delta.start.row > this.row) return; - + var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); this.setPosition(point.row, point.column, true); } diff --git a/src/autocomplete.js b/src/autocomplete.js index 520c74ec070..a46dfc3704b 100644 --- a/src/autocomplete.js +++ b/src/autocomplete.js @@ -3,6 +3,7 @@ * @typedef {import("./editor").Editor} Editor * @typedef {import("../ace-internal").Ace.CompletionProviderOptions} CompletionProviderOptions * @typedef {import("../ace-internal").Ace.CompletionOptions} CompletionOptions + * @typedef {import("../ace-internal").Ace.Position} Position */ var HashHandler = require("./keyboard/hash_handler").HashHandler; var AcePopup = require("./autocomplete/popup").AcePopup; @@ -31,7 +32,7 @@ var preventParentScroll = require("./lib/scroll").preventParentScroll; * @property {string} [command] - A command to be executed after the completion is inserted (experimental) * @property {string} [snippet] - a text snippet that would be inserted when the completion is selected * @property {string} [value] - The text that would be inserted when selecting this completion. - * @property {import("../ace-internal").Ace.Completer & {insertMatch:(editor: Editor, data: Completion) => void}} [completer] + * @property {import("../ace-internal").Ace.Completer} [completer] * @property {boolean} [hideInlinePreview] * @export */ @@ -76,10 +77,11 @@ class Autocomplete { this.keyboardHandler.bindKeys(this.commands); this.parentNode = null; this.setSelectOnHover = false; + /**@private*/ this.hasSeen = new Set(); /** - * @property {Boolean} showLoadingState - A boolean indicating whether the loading states of the Autocompletion should be shown to the end-user. If enabled + * @property {Boolean} showLoadingState - A boolean indicating whether the loading states of the Autocompletion should be shown to the end-user. If enabled * it shows a loading indicator on the popup while autocomplete is loading. * * Experimental: This visualisation is not yet considered stable and might change in the future. @@ -255,6 +257,10 @@ class Autocomplete { }); this.$elements = null; } + + /** + * @internal + */ onLayoutChange() { if (!this.popup.isOpen) return this.unObserveLayoutChanges(); this.$updatePopupPosition(); @@ -470,7 +476,7 @@ class Autocomplete { /** * This is the entry point for the autocompletion class, triggers the actions which collect and display suggestions * @param {Editor} editor - * @param {CompletionOptions} options + * @param {CompletionOptions} [options] */ showPopup(editor, options) { if (this.editor) @@ -493,6 +499,11 @@ class Autocomplete { this.updateCompletions(false, options); } + /** + * + * @param {{pos: Position, prefix: string}} [initialPosition] + * @return {CompletionProvider} + */ getCompletionProvider(initialPosition) { if (!this.completionProvider) this.completionProvider = new CompletionProvider(initialPosition); @@ -510,7 +521,7 @@ class Autocomplete { /** * @param {boolean} keepPopupPosition - * @param {CompletionOptions} options + * @param {CompletionOptions} [options] */ updateCompletions(keepPopupPosition, options) { if (keepPopupPosition && this.base && this.completions) { @@ -705,7 +716,11 @@ class Autocomplete { if (el.parentNode) el.parentNode.removeChild(el); } - + + /** + * @param e + * @internal + */ onTooltipClick(e) { var a = e.target; while (a && a != this.tooltipNode) { @@ -733,6 +748,30 @@ class Autocomplete { this.inlineRenderer = this.popup = this.editor = null; } + /** + * @param {Editor} editor + * @return {Autocomplete} + */ + static for(editor) { + if (editor.completer instanceof Autocomplete) { + return editor.completer; + } + if (editor.completer) { + editor.completer.destroy(); + editor.completer = null; + } + if (config.get("sharedPopups")) { + if (!Autocomplete["$sharedInstance"]) + Autocomplete["$sharedInstance"] = new Autocomplete(); + editor.completer = Autocomplete["$sharedInstance"]; + } else { + editor.completer = new Autocomplete(); + editor.once("destroy", destroyCompleter); + } + // @ts-expect-error + return editor.completer; + } + } Autocomplete.prototype.commands = { @@ -762,26 +801,6 @@ Autocomplete.prototype.commands = { "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); } }; - -Autocomplete.for = function(editor) { - if (editor.completer instanceof Autocomplete) { - return editor.completer; - } - if (editor.completer) { - editor.completer.destroy(); - editor.completer = null; - } - if (config.get("sharedPopups")) { - if (!Autocomplete["$sharedInstance"]) - Autocomplete["$sharedInstance"] = new Autocomplete(); - editor.completer = Autocomplete["$sharedInstance"]; - } else { - editor.completer = new Autocomplete(); - editor.once("destroy", destroyCompleter); - } - return editor.completer; -}; - Autocomplete.startCommand = { name: "startAutocomplete", exec: function(editor, options) { @@ -803,7 +822,7 @@ class CompletionProvider { /** - * @param {{pos: import("../ace-internal").Ace.Position, prefix: string}} initialPosition + * @param {{pos: Position, prefix: string}} [initialPosition] */ constructor(initialPosition) { this.initialPosition = initialPosition; diff --git a/src/bidihandler.js b/src/bidihandler.js index 003822fcafd..20f023613e2 100644 --- a/src/bidihandler.js +++ b/src/bidihandler.js @@ -39,7 +39,7 @@ class BidiHandler { this.isMoveLeftOperation = false; this.seenBidi = bidiRE.test(session.getValue()); } - + /** * Returns 'true' if row contains Bidi characters, in such case * creates Bidi map to be used in operations related to selection @@ -59,13 +59,17 @@ class BidiHandler { return this.bidiMap.bidiLevels; } + /** + * @param {import("../ace-internal").Ace.Delta} delta + * @internal + */ onChange(delta) { if (!this.seenBidi) { if (delta.action == "insert" && bidiRE.test(delta.lines.join("\n"))) { this.seenBidi = true; this.currentRow = null; } - } + } else { this.currentRow = null; } @@ -106,7 +110,7 @@ class BidiHandler { updateRowLine(docRow, splitIndex) { if (docRow === undefined) docRow = this.getDocumentRow(); - + var isLastRow = (docRow === this.session.getLength() - 1), endOfLine = isLastRow ? this.EOF : this.EOL; @@ -136,7 +140,7 @@ class BidiHandler { } else { this.line += this.showInvisibles ? endOfLine : bidiUtil.DOT; } - + /* replace tab and wide characters by commensurate spaces */ var session = this.session, shift = 0, size; this.line = this.line.replace(/\t|[\u1100-\u2029, \u202F-\uFFE6]/g, function(ch, i){ @@ -153,7 +157,7 @@ class BidiHandler { this.rtlLineOffset = this.contentWidth - this.fontMetrics.$main.getBoundingClientRect().width; } } - + updateBidiMap() { var textCharTypes = []; if (bidiUtil.hasBidiCharacters(this.line, textCharTypes) || this.isRtlDir) { @@ -197,7 +201,7 @@ class BidiHandler { } setEolChar(eolChar) { - this.EOL = eolChar; + this.EOL = eolChar; } setContentWidth(width) { @@ -209,11 +213,11 @@ class BidiHandler { if (row != undefined) return (this.session.getLine(row).charAt(0) == this.RLE); else - return this.isRtlDir; + return this.isRtlDir; } setRtlDirection(editor, isRtlDir) { - var cursor = editor.getCursorPosition(); + var cursor = editor.getCursorPosition(); for (var row = editor.selection.getSelectionAnchor().row; row <= cursor.row; row++) { if (!isRtlDir && editor.session.getLine(row).charAt(0) === editor.session.$bidiHandler.RLE) editor.session.doc.removeInLine(row, 0, 1); @@ -238,7 +242,7 @@ class BidiHandler { if (!this.session.getOverwrite() && col <= leftBoundary && levels[visualIdx] % 2 !== 0) visualIdx++; - + for (var i = 0; i < visualIdx; i++) { left += this.charWidths[levels[i]]; } @@ -266,7 +270,7 @@ class BidiHandler { var map = this.bidiMap, levels = map.bidiLevels, level, selections = [], offset = 0, selColMin = Math.min(startCol, endCol) - this.wrapIndent, selColMax = Math.max(startCol, endCol) - this.wrapIndent, isSelected = false, isSelectedPrev = false, selectionStart = 0; - + if (this.wrapIndent) offset += this.isRtlDir ? (-1 * this.wrapOffset) : this.wrapOffset; @@ -311,7 +315,7 @@ class BidiHandler { if (this.wrapIndent) posX -= this.isRtlDir ? (-1 * this.wrapOffset) : this.wrapOffset; - + while(posX > offset + charWidth/2) { offset += charWidth; if(visualIdx === levels.length - 1) { @@ -321,7 +325,7 @@ class BidiHandler { } charWidth = this.charWidths[levels[++visualIdx]]; } - + if (visualIdx > 0 && (levels[visualIdx - 1] % 2 !== 0) && (levels[visualIdx] % 2 === 0)){ /* Bidi character on the left and None Bidi character on the right */ if(posX < offset) diff --git a/src/config.js b/src/config.js index 0a76b117f4b..d4662231f17 100644 --- a/src/config.js +++ b/src/config.js @@ -6,6 +6,7 @@ var AppConfig = require("./lib/app_config").AppConfig; module.exports = exports = new AppConfig(); +/** @type {import("../ace-internal").Ace.ConfigOptions} */ var options = { packaged: false, workerPath: null, @@ -20,8 +21,9 @@ var options = { }; /** - * @param {string} key - * @return {*} + * @template {keyof import("../ace-internal").Ace.ConfigOptions} K + * @param {K} key - The key of the config option to retrieve. + * @returns {import("../ace-internal").Ace.ConfigOptions[K]} - The value of the config option. */ exports.get = function(key) { if (!options.hasOwnProperty(key)) @@ -30,8 +32,9 @@ exports.get = function(key) { }; /** - * @param {string} key - * @param value + * @template {keyof import("../ace-internal").Ace.ConfigOptions} K + * @param {K} key + * @param {import("../ace-internal").Ace.ConfigOptions[K]} value */ exports.set = function(key, value) { if (options.hasOwnProperty(key)) @@ -42,7 +45,7 @@ exports.set = function(key, value) { dom.useStrictCSP(value); }; /** - * @return {{[key: string]: any}} + * @return {import("../ace-internal").Ace.ConfigOptions} */ exports.all = function() { return lang.copyObject(options); @@ -100,9 +103,6 @@ var loader = function(moduleName, cb) { console.error("loader is not configured"); }; var customLoader; -/** - * @param {(moduleName: string, afterLoad: (err: Error | null, module: unknown) => void) => void}cb - */ exports.setLoader = function(cb) { customLoader = cb; }; diff --git a/src/edit_session.js b/src/edit_session.js index 0546545c505..7fef86d933d 100644 --- a/src/edit_session.js +++ b/src/edit_session.js @@ -54,10 +54,10 @@ class EditSession { return this.join("\n"); }; - // Set default background tokenizer with Text mode until editor session mode is set + // Set default background tokenizer with Text mode until editor session mode is set this.bgTokenizer = new BackgroundTokenizer((new TextMode()).getTokenizer(), this); - + var _self = this; this.bgTokenizer.on("update", function(e) { _self._signal("tokenizerUpdate", e); @@ -135,7 +135,7 @@ class EditSession { /** * End current Ace operation. * Emits "beforeEndOperation" event just before clearing everything, where the current operation can be accessed through `curOp` property. - * @param {any} e + * @param {any} e */ endOperation(e) { if (this.curOp) { @@ -235,14 +235,19 @@ class EditSession { this.bgTokenizer.start(0); } + /** + * @param e + * @internal + */ onChangeFold(e) { var fold = e.data; this.$resetRowCache(fold.start.row); } /** - * + * * @param {Delta} delta + * @internal */ onChange(delta) { this.$modified = true; @@ -261,7 +266,7 @@ class EditSession { } this.$undoManager.add(delta, this.mergeUndoDeltas); this.mergeUndoDeltas = true; - + this.$informUndoManager.schedule(); } @@ -300,7 +305,7 @@ class EditSession { undoManager.$redoStack = session.history.redo; undoManager.mark = session.history.mark; undoManager.$rev = session.history.rev; - + const editSession = new EditSession(session.value); session.folds.forEach(function(fold) { editSession.addFold("...", Range.fromPoints(fold.start, fold.end)); @@ -312,10 +317,10 @@ class EditSession { editSession.setScrollTop(session.scrollTop); editSession.setUndoManager(undoManager); editSession.selection.fromJSON(session.selection); - + return editSession; } - + /** * Returns the current edit session. * @method toJSON @@ -336,7 +341,7 @@ class EditSession { value: this.doc.getValue() }; } - + /** * Returns the current [[Document `Document`]] as a string. * @method toString @@ -409,10 +414,10 @@ class EditSession { **/ setUndoManager(undoManager) { this.$undoManager = undoManager; - + if (this.$informUndoManager) this.$informUndoManager.cancel(); - + if (undoManager) { var self = this; undoManager.addSession(this); @@ -462,7 +467,7 @@ class EditSession { setUseSoftTabs(val) { this.setOption("useSoftTabs", val); } - + /** * Returns `true` if soft tabs are being used, `false` otherwise. * @returns {Boolean} @@ -861,13 +866,14 @@ class EditSession { /** * Reloads all the tokens on the current session. This function calls [[BackgroundTokenizer.start `BackgroundTokenizer.start ()`]] to all the rows; it also emits the `'tokenizerUpdate'` event. + * @internal **/ onReloadTokenizer(e) { var rows = e.data; this.bgTokenizer.start(rows.first); this._signal("tokenizerUpdate", e); } - + /** * Sets a new text mode for the `EditSession`. This method also emits the `'changeMode'` event. If a [[BackgroundTokenizer `BackgroundTokenizer`]] is set, the `'tokenizerUpdate'` event is also emitted. * @param {SyntaxMode | string} mode Set a new text mode @@ -922,9 +928,9 @@ class EditSession { $onChangeMode(mode, $isPlaceholder) { if (!$isPlaceholder) this.$modeId = mode.$id; - if (this.$mode === mode) + if (this.$mode === mode) return; - + var oldMode = this.$mode; this.$mode = mode; @@ -948,7 +954,7 @@ class EditSession { /**@type {RegExp}*/ this.nonTokenRe = mode.nonTokenRe; - + if (!$isPlaceholder) { // experimental method, used by c9 findiniles if (mode.attachToSession) @@ -989,7 +995,7 @@ class EditSession { * @param {Number} scrollTop The new scroll top value **/ setScrollTop(scrollTop) { - // TODO: should we force integer lineheight instead? scrollTop = Math.round(scrollTop); + // TODO: should we force integer lineheight instead? scrollTop = Math.round(scrollTop); if (this.$scrollTop === scrollTop || isNaN(scrollTop)) return; @@ -1032,7 +1038,7 @@ class EditSession { **/ getScreenWidth() { this.$computeWidth(); - if (this.lineWidgets) + if (this.lineWidgets) return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth); return this.screenWidth; } @@ -1144,7 +1150,7 @@ class EditSession { remove(range) { return this.doc.remove(range); } - + /** * Removes a range of full lines. This method also triggers the `'change'` event. * @param {Number} firstRow The first row to be removed @@ -1218,14 +1224,14 @@ class EditSession { /** * Enables or disables highlighting of the range where an undo occurred. * @param {Boolean} enable If `true`, selects the range of the reinserted change - * + * **/ setUndoSelect(enable) { this.$undoSelect = enable; } /** - * + * * @param {Delta[]} deltas * @param {boolean} [isUndo] * @return {Range} @@ -1248,7 +1254,7 @@ class EditSession { } continue; } - + if (isInsert(delta)) { point = delta.start; if (range.compare(point.row, point.column) == -1) { @@ -1381,7 +1387,7 @@ class EditSession { } /** - * + * * @param {number} firstRow * @param {number} lastRow * @param [dir] @@ -1411,7 +1417,7 @@ class EditSession { x.end.row += diff; return x; }); - + var lines = dir == 0 ? this.doc.getLines(firstRow, lastRow) : this.doc.removeFullLines(firstRow, lastRow); @@ -1521,7 +1527,7 @@ class EditSession { } return range; } - + /** * Sets whether or not line wrapping is enabled. If `useWrapMode` is different than the current value, the `'changeWrapMode'` event is emitted. * @param {Boolean} useWrapMode Enable (or disable) wrap mode @@ -1597,7 +1603,7 @@ class EditSession { } /** - * + * * @param {number} wrapLimit * @param {number} [min] * @param {number} [max] @@ -1620,7 +1626,7 @@ class EditSession { getWrapLimit() { return this.$wrapLimit; } - + /** * Sets the line length for soft wrap in the editor. Lines will break * at a minimum of the given length minus 20 chars and at a maximum @@ -1630,7 +1636,7 @@ class EditSession { setWrapLimit(limit) { this.setWrapLimitRange(limit, limit); } - + /** * Returns an object that defines the minimum and maximum of the wrap limit; it looks something like this: * @@ -1658,7 +1664,7 @@ class EditSession { var lastRow = end.row; var len = lastRow - firstRow; var removedFolds = null; - + this.$updating = true; if (len != 0) { if (action === "remove") { @@ -2053,13 +2059,13 @@ class EditSession { var h = 1; if (this.lineWidgets) h += this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; - + if (!this.$useWrapMode || !this.$wrapData[row]) return h; else return this.$wrapData[row].length + h; } - + /** * @param {Number} row * @returns {Number} @@ -2351,7 +2357,7 @@ class EditSession { wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0; } } - + if (this.lineWidgets && this.lineWidgets[row] && this.lineWidgets[row].rowsAbove) screenRow += this.lineWidgets[row].rowsAbove; @@ -2434,7 +2440,7 @@ class EditSession { if (!maxScreenColumn) maxScreenColumn = Infinity; screenColumn = screenColumn || 0; - + var c, column; for (column = 0; column < str.length; column++) { c = str.charAt(column); @@ -2448,7 +2454,7 @@ class EditSession { break; } } - + return [screenColumn, column]; }; } @@ -2522,7 +2528,7 @@ EditSession.prototype.$wrapLimitRange = { max : null }; /** - * + * * @type {null | import("../ace-internal").Ace.LineWidget[]} */ EditSession.prototype.lineWidgets = null; @@ -2619,7 +2625,7 @@ config.defineOptions(EditSession.prototype, "session", { return "off"; }, handlesSet: true - }, + }, wrapMethod: { /** * @param {"code"|"text"|"auto"|boolean} val @@ -2649,7 +2655,7 @@ config.defineOptions(EditSession.prototype, "session", { this.setUseWrapMode(true); } }, - initialValue: true + initialValue: true }, firstLineNumber: { set: function() {this._signal("changeBreakpoint");}, diff --git a/src/editor.js b/src/editor.js index 62e1d613910..2ad6199af47 100644 --- a/src/editor.js +++ b/src/editor.js @@ -49,9 +49,9 @@ class Editor { constructor(renderer, session, options) { /**@type{EditSession}*/this.session; this.$toDestroy = []; - + var container = renderer.getContainerElement(); - /**@type {HTMLElement & {env?, value?}}*/ + /**@type {HTMLElement & {env?:any, value?:any}}*/ this.container = container; /**@type {VirtualRenderer}*/ this.renderer = renderer; @@ -104,7 +104,7 @@ class Editor { this.session.startOperation(commandEvent); } - /** + /** * @arg e */ endOperation(e) { @@ -121,7 +121,7 @@ class Editor { } } - /** + /** * @arg e */ onEndOperation(e) { @@ -168,7 +168,7 @@ class Editor { } } - /** + /** * @param e */ $historyTracker(e) { @@ -238,7 +238,7 @@ class Editor { } - + /** * Sets a new editsession to use. This method also emits the `'changeSession'` event. * @param {EditSession} [session] The new session to use @@ -246,7 +246,7 @@ class Editor { setSession(session) { if (this.session == session) return; - + // make sure operationEnd events are not emitted to wrong session if (this.curOp) this.endOperation(); this.curOp = {}; @@ -280,49 +280,49 @@ class Editor { this.$onDocumentChange = this.onDocumentChange.bind(this); session.on("change", this.$onDocumentChange); this.renderer.setSession(session); - + this.$onChangeMode = this.onChangeMode.bind(this); session.on("changeMode", this.$onChangeMode); - + this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); session.on("tokenizerUpdate", this.$onTokenizerUpdate); - + this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); session.on("changeTabSize", this.$onChangeTabSize); - + this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); session.on("changeWrapLimit", this.$onChangeWrapLimit); - + this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); session.on("changeWrapMode", this.$onChangeWrapMode); - + this.$onChangeFold = this.onChangeFold.bind(this); session.on("changeFold", this.$onChangeFold); - + this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); this.session.on("changeFrontMarker", this.$onChangeFrontMarker); - + this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); this.session.on("changeBackMarker", this.$onChangeBackMarker); - + this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); this.session.on("changeBreakpoint", this.$onChangeBreakpoint); - + this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); this.session.on("changeAnnotation", this.$onChangeAnnotation); - + this.$onCursorChange = this.onCursorChange.bind(this); this.session.on("changeOverwrite", this.$onCursorChange); - + this.$onScrollTopChange = this.onScrollTopChange.bind(this); this.session.on("changeScrollTop", this.$onScrollTopChange); - + this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); this.session.on("changeScrollLeft", this.$onScrollLeftChange); - + this.selection = session.getSelection(); this.selection.on("changeCursor", this.$onCursorChange); - + this.$onSelectionChange = this.onSelectionChange.bind(this); this.selection.on("changeSelection", this.$onSelectionChange); @@ -330,11 +330,11 @@ class Editor { this.session.on("startOperation", this.$onStartOperation); this.$onEndOperation = this.onEndOperation.bind(this); this.session.on("endOperation", this.$onEndOperation); - + this.onChangeMode(); - + this.onCursorChange(); - + this.onScrollTopChange(); this.onScrollLeftChange(); this.onSelectionChange(); @@ -353,12 +353,12 @@ class Editor { session: session, oldSession: oldSession }); - + this.curOp = null; - + oldSession && oldSession._signal("changeEditor", {oldEditor: this}); session && session._signal("changeEditor", {editor: this}); - + if (session && !session.destroyed) session.bgTokenizer.scheduleStart(); } @@ -459,7 +459,7 @@ class Editor { /** * Gets the current font size of the editor text. - * @return {string} + * @return {string | number} */ getFontSize() { return this.getOption("fontSize") || @@ -468,7 +468,7 @@ class Editor { /** * Set a new font size (in pixels) for the editor text. - * @param {String} size A font size ( _e.g._ "12px") + * @param {String | number} size A font size ( _e.g._ "12px") **/ setFontSize(size) { this.setOption("fontSize", size); @@ -569,6 +569,7 @@ class Editor { /** * Emitted once the editor comes into focus. + * @internal **/ onFocus(e) { if (this.$isFocused) @@ -581,6 +582,7 @@ class Editor { /** * Emitted once the editor has been blurred. + * @internal **/ onBlur(e) { if (!this.$isFocused) @@ -602,6 +604,7 @@ class Editor { /** * Emitted whenever the document is changed. * @param {import("../ace-internal").Ace.Delta} delta Contains a single property, `data`, which has the delta of changes + * @internal **/ onDocumentChange(delta) { // Rerender and emit "change" event. @@ -610,27 +613,36 @@ class Editor { this.renderer.updateLines(delta.start.row, lastRow, wrap); this._signal("change", delta); - + // Update cursor because tab characters can influence the cursor position. this.$cursorChange(); } + /** + * @internal + */ onTokenizerUpdate(e) { var rows = e.data; this.renderer.updateLines(rows.first, rows.last); } - + /** + * @internal + */ onScrollTopChange() { this.renderer.scrollToY(this.session.getScrollTop()); } + /** + * @internal + */ onScrollLeftChange() { this.renderer.scrollToX(this.session.getScrollLeft()); } /** * Emitted when the selection changes. + * @internal **/ onCursorChange() { this.$cursorChange(); @@ -668,8 +680,8 @@ class Editor { } /** - * * @param e + * @internal */ onSelectionChange(e) { var session = this.session; @@ -703,9 +715,9 @@ class Editor { var startColumn = selection.start.column; var endColumn = selection.end.column; var line = session.getLine(selection.start.row); - + var needle = line.substring(startColumn, endColumn); - // maximum allowed size for regular expressions in 32000, + // maximum allowed size for regular expressions in 32000, // but getting close to it has significant impact on the performance if (needle.length > 5000 || !/[\w\d]/.test(needle)) return; @@ -715,51 +727,68 @@ class Editor { caseSensitive: true, needle: needle }); - + var wordWithBoundary = line.substring(startColumn - 1, endColumn + 1); if (!re.test(wordWithBoundary)) return; - + return re; } - + /** + * @internal + */ onChangeFrontMarker() { this.renderer.updateFrontMarkers(); } + /** + * @internal + */ onChangeBackMarker() { this.renderer.updateBackMarkers(); } - + /** + * @internal + */ onChangeBreakpoint() { this.renderer.updateBreakpoints(); } + /** + * @internal + */ onChangeAnnotation() { this.renderer.setAnnotations(this.session.getAnnotations()); } /** * @param e + * @internal */ onChangeMode (e) { this.renderer.updateText(); this._emit("changeMode", e); } - + /** + * @internal + */ onChangeWrapLimit() { this.renderer.updateFull(); } + /** + * @internal + */ onChangeWrapMode() { this.renderer.onResize(true); } /** + * @internal */ onChangeFold() { // Update the active line marker as due to folding changes the current @@ -769,7 +798,7 @@ class Editor { this.renderer.updateFull(); } - + /** * Returns the string of text currently highlighted. * @returns {String} @@ -777,8 +806,8 @@ class Editor { getSelectedText() { return this.session.getTextRange(this.getSelectionRange()); } - - + + /** * Returns the string of text currently highlighted. * @returns {String} @@ -805,6 +834,7 @@ class Editor { /** * Called whenever a text "copy" happens. + * @internal **/ onCopy() { this.commands.exec("copy", this); @@ -812,6 +842,7 @@ class Editor { /** * Called whenever a text "cut" happens. + * @internal **/ onCut() { this.commands.exec("cut", this); @@ -822,6 +853,7 @@ class Editor { * Called whenever a text "paste" happens. * @param {String} text The pasted text * @param {any} event + * @internal **/ onPaste(text, event) { var e = {text: text, event: event}; @@ -829,12 +861,12 @@ class Editor { } /** - * + * * @param e * @returns {boolean} */ $handlePaste(e) { - if (typeof e == "string") + if (typeof e == "string") e = {text: e}; this._signal("paste", e); var text = e.text; @@ -853,23 +885,23 @@ class Editor { } else { var lines = text.split(/\r\n|\r|\n/); var ranges = this.selection.rangeList.ranges; - + var isFullLine = lines.length == 2 && (!lines[0] || !lines[1]); if (lines.length != ranges.length || isFullLine) return this.commands.exec("insertstring", this, text); - + for (var i = ranges.length; i--;) { var range = ranges[i]; if (!range.isEmpty()) session.remove(range); - + session.insert(range.start, lines[i]); } } } /** - * + * * @param {string | string[]} command * @param [args] * @return {boolean} @@ -903,7 +935,7 @@ class Editor { } } - + if (text == "\t") text = this.session.getTabString(); @@ -974,7 +1006,7 @@ class Editor { for (var i = 0; i < ranges.length; i++) { var startRow = ranges[i].start.row; var endRow = ranges[i].end.row; - + for (var row = startRow; row <= endRow; row++) { if (row > 0) { prevLineState = session.getState(row - 1); @@ -1000,15 +1032,16 @@ class Editor { } /** - * + * * @param text * @param composition * @returns {*} + * @internal */ onTextInput(text, composition) { if (!composition) return this.keyBinding.onTextInput(text); - + this.startOperation({command: { name: "insertstring" }}); var applyComposition = this.applyComposition.bind(this, text, composition); if (this.selection.rangeCount) @@ -1045,6 +1078,9 @@ class Editor { } } + /** + * @internal + */ onCommandKey(e, hashId, keyCode) { return this.keyBinding.onCommandKey(e, hashId, keyCode); } @@ -1118,7 +1154,7 @@ class Editor { /** * Returns the current selection style. - * @returns {import("../ace-internal").Ace.EditorOptions["selectionStyle"]} + * @returns {import("../ace-internal").Ace.EditorOptions["selectionStyle"]} **/ getSelectionStyle() { return this.getOption("selectionStyle"); @@ -1351,7 +1387,7 @@ class Editor { else this.selection.selectRight(); } - + var range = this.getSelectionRange(); if (this.getBehavioursEnabled()) { var session = this.session; @@ -1445,7 +1481,7 @@ class Editor { * Set the "ghost" text in provided position. "Ghost" text is a kind of * preview text inside the editor which can be used to preview some code * inline in the editor such as, for example, code completions. - * + * * @param {String} text Text to be inserted as "ghost" text * @param {Point} [position] Position to insert text to */ @@ -1544,7 +1580,7 @@ class Editor { return; } } - + var line = session.getLine(range.start.row); var position = range.start; var size = session.getTabSize(); @@ -1837,7 +1873,7 @@ class Editor { * @param {Range} range The range of text you want moved within the document * @param {Point} toPosition The location (row and column) where you want to move the text to * @param {boolean} [copy] - * + * * @returns {Range} The new range where the text was moved to. * @related EditSession.moveText **/ @@ -1882,7 +1918,7 @@ class Editor { // @ts-expect-error TODO: possible bug, no args in parameters selection.rangeList.detach(this.session); this.inVirtualSelectionMode = true; - + var diff = 0; var totalDiff = 0; var l = ranges.length; @@ -1911,7 +1947,7 @@ class Editor { if (!copy) diff = 0; totalDiff += diff; } - + selection.fromOrientedRange(selection.ranges[0]); selection.rangeList.attach(this.session); this.inVirtualSelectionMode = false; @@ -1936,14 +1972,23 @@ class Editor { }; } + /** + * @internal + */ onCompositionStart(compositionState) { this.renderer.showComposition(compositionState); } + /** + * @internal + */ onCompositionUpdate(text) { this.renderer.setCompositionText(text); } + /** + * @internal + */ onCompositionEnd() { this.renderer.hideComposition(); } @@ -2127,7 +2172,7 @@ class Editor { getSelectionRange() { return this.selection.getRange(); } - + /** * Selects all the text in editor. * @related Selection.selectAll @@ -2610,7 +2655,7 @@ class Editor { } /** - * + * * @param {Range} range * @param {boolean} [animate] */ @@ -2798,7 +2843,7 @@ config.defineOptions(Editor.prototype, "editor", { readOnly: { set: function(readOnly) { this.textInput.setReadOnly(readOnly); - this.$resetCursorStyle(); + this.$resetCursorStyle(); }, initialValue: false }, @@ -2840,7 +2885,7 @@ config.defineOptions(Editor.prototype, "editor", { handlesSet: true, hidden: true }, - + showLineNumbers: { set: function(show) { this.renderer.$gutterLayer.setShowLineNumbers(show); @@ -2909,10 +2954,10 @@ config.defineOptions(Editor.prototype, "editor", { if (e.target == this.renderer.scroller && e.keyCode === keys['enter']){ e.preventDefault(); var row = this.getCursorPosition().row; - + if (!this.isRowVisible(row)) this.scrollToLine(row, true, true); - + this.focus(); } }; @@ -2973,7 +3018,7 @@ config.defineOptions(Editor.prototype, "editor", { this.renderer.scroller.removeAttribute("aria-roledescription"); this.renderer.scroller.classList.remove(this.renderer.keyboardFocusClassName); this.renderer.scroller.removeAttribute("aria-label"); - + this.renderer.scroller.removeEventListener("keyup", focusOnEnterKeyup.bind(this)); this.commands.removeCommand(blurCommand); diff --git a/src/ext/code_lens.js b/src/ext/code_lens.js index 7a2c89a1228..7098c1e9984 100644 --- a/src/ext/code_lens.js +++ b/src/ext/code_lens.js @@ -1,7 +1,7 @@ "use strict"; /** * @typedef {import("../edit_session").EditSession} EditSession - * @typedef {import("../virtual_renderer").VirtualRenderer & {$textLayer: import("../layer/text").Text &{$lenses}}} VirtualRenderer + * @typedef {import("../virtual_renderer").VirtualRenderer & {$textLayer: import("../layer/text").Text &{$lenses: any}}} VirtualRenderer */ var LineWidgets = require("../line_widgets").LineWidgets; @@ -108,9 +108,9 @@ function clearCodeLensWidgets(session) { } /** - * + * * @param {EditSession} session - * @param lenses + * @param {import("../../ace-internal").Ace.CodeLense[]} lenses * @return {number} */ exports.setLenses = function(session, lenses) { @@ -189,7 +189,7 @@ function attachToEditor(editor) { var row = session.documentToScreenRow(cursor); var lineHeight = editor.renderer.layerConfig.lineHeight; var top = session.getScrollTop() + (row - oldRow) * lineHeight; - // special case for the lens on line 0, because it can't be scrolled into view with keyboard + // special case for the lens on line 0, because it can't be scrolled into view with keyboard if (firstRow == 0 && scrollTop < lineHeight /4 && scrollTop > -lineHeight/4) { top = -lineHeight; } @@ -215,7 +215,7 @@ function detachFromEditor(editor) { /** * @param {import("../editor").Editor} editor - * @param codeLensProvider + * @param {import("../../ace-internal").Ace.CodeLenseProvider} codeLensProvider */ exports.registerCodeLensProvider = function(editor, codeLensProvider) { editor.setOption("enableCodeLens", true); diff --git a/src/ext/searchbox.js b/src/ext/searchbox.js index f676da50803..e26a9003919 100644 --- a/src/ext/searchbox.js +++ b/src/ext/searchbox.js @@ -17,8 +17,8 @@ dom.importCssString(searchboxCss, "ace_searchbox", false); class SearchBox { /** * @param {Editor} editor - * @param {undefined} [range] - * @param {undefined} [showReplaceForm] + * @param {never} [range] + * @param {never} [showReplaceForm] */ constructor(editor, range, showReplaceForm) { /**@type {any}*/ @@ -66,7 +66,7 @@ class SearchBox { /**@type {Editor}*/ this.editor = editor; } - + setSession(e) { this.searchRange = null; this.$syncOptions(true); @@ -97,12 +97,12 @@ class SearchBox { /**@type {HTMLElement}*/ this.searchCounter = sb.querySelector(".ace_search_counter"); } - + $init() { var sb = this.element; - + this.$initElements(sb); - + var _this = this; event.addListener(sb, "mousedown", function(e) { setTimeout(function(){ @@ -213,11 +213,11 @@ class SearchBox { var value = this.searchRange ? editor.session.getTextRange(this.searchRange) : editor.getValue(); - + var offset = editor.session.doc.positionToIndex(editor.selection.anchor); if (this.searchRange) offset -= editor.session.doc.positionToIndex(this.searchRange.start); - + var last = regex.lastIndex = 0; var m; while ((m = regex.exec(value))) { @@ -243,7 +243,7 @@ class SearchBox { this.find(true, true); } findAll(){ - var range = this.editor.findAll(this.searchInput.value, { + var range = this.editor.findAll(this.searchInput.value, { regExp: this.regExpOption.checked, caseSensitive: this.caseSensitiveOption.checked, wholeWord: this.wholeWordOption.checked @@ -258,7 +258,7 @@ class SearchBox { replace() { if (!this.editor.getReadOnly()) this.editor.replace(this.replaceInput.value); - } + } replaceAndFindNext() { if (!this.editor.getReadOnly()) { this.editor.replace(this.replaceInput.value); @@ -274,7 +274,7 @@ class SearchBox { this.active = false; this.setSearchRange(null); this.editor.off("changeSession", this.setSession); - + this.element.style.display = "none"; this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); this.editor.focus(); @@ -289,15 +289,15 @@ class SearchBox { this.editor.on("changeSession", this.setSession); this.element.style.display = ""; this.replaceOption.checked = isReplace; - + if (value) this.searchInput.value = value; - + this.searchInput.focus(); this.searchInput.select(); this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); - + this.$syncOptions(true); } @@ -404,7 +404,7 @@ SearchBox.prototype.$closeSearchBarKb = $closeSearchBarKb; exports.SearchBox = SearchBox; /** - * + * * @param {Editor} editor * @param {boolean} [isReplace] */ diff --git a/src/ext/static_highlight.js b/src/ext/static_highlight.js index 427f626a8d4..ada36bfc023 100644 --- a/src/ext/static_highlight.js +++ b/src/ext/static_highlight.js @@ -1,4 +1,9 @@ "use strict"; +/** + * @typedef {import("../../ace-internal").Ace.SyntaxMode} SyntaxMode + * @typedef {import("../../ace-internal").Ace.Theme} Theme + */ + var EditSession = require("../edit_session").EditSession; var TextLayer = require("../layer/text").Text; @@ -75,9 +80,9 @@ var SimpleTextLayer = function() { SimpleTextLayer.prototype = TextLayer.prototype; /** - * + * * @param {HTMLElement} el - * @param opts + * @param {import("../../ace-internal").Ace.StaticHighlightOptions} opts * @param [callback] * @returns {boolean} */ @@ -87,7 +92,7 @@ var highlight = function(el, opts, callback) { if (!mode) return false; var theme = opts.theme || "ace/theme/textmate"; - + var data = ""; var nodes = []; @@ -108,13 +113,13 @@ var highlight = function(el, opts, callback) { if (opts.trim) data = data.trim(); } - + highlight.render(data, mode, theme, opts.firstLineNumber, !opts.showGutter, function (highlighted) { dom.importCssString(highlighted.css, "ace_highlight", true); el.innerHTML = highlighted.html; - /** + /** * TODO: check if child exists - * @type {any} + * @type {any} */ var container = el.firstChild.firstChild; for (var i = 0; i < nodes.length; i += 2) { @@ -131,10 +136,10 @@ var highlight = function(el, opts, callback) { * Transforms a given input code snippet into HTML using the given mode * * @param {string} input Code snippet - * @param {string|import("../../ace-internal").Ace.SyntaxMode} mode String specifying the mode to load such as + * @param {string | SyntaxMode} mode String specifying the mode to load such as * `ace/mode/javascript` or, a mode loaded from `/ace/mode` * (use 'ServerSideHiglighter.getMode'). - * @param {string} theme String specifying the theme to load such as + * @param {string | Theme} theme String specifying the theme to load such as * `ace/theme/twilight` or, a theme loaded from `/ace/theme`. * @param {number} lineStart A number indicating the first line number. Defaults * to 1. @@ -177,7 +182,7 @@ highlight.render = function(input, mode, theme, lineStart, disableGutter, callba // loads or passes the specified mode module then calls renderer function done() { - var result = highlight.renderSync(input, mode, theme, lineStart, disableGutter); + var result = highlight.renderSync(input, mode, /**@type{Theme}*/(theme), lineStart, disableGutter); return callback ? callback(result) : result; } return --waiting || done(); @@ -186,8 +191,8 @@ highlight.render = function(input, mode, theme, lineStart, disableGutter, callba /** * Transforms a given input code snippet into HTML using the given mode * @param {string} input Code snippet - * @param {import("../../ace-internal").Ace.SyntaxMode|string} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode') - * @param {any} theme + * @param {SyntaxMode | string} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode') + * @param {Theme} theme * @param {any} lineStart * @param {boolean} disableGutter * @returns {object} An object containing: html, css @@ -212,10 +217,10 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { session.setValue(input); var length = session.getLength(); - + var outerEl = simpleDom.createElement("div"); outerEl.className = theme.cssClass; - + var innerEl = simpleDom.createElement("div"); innerEl.className = "ace_static_highlight" + (disableGutter ? "" : " ace_show_gutter"); innerEl.style["counter-reset"] = "ace_line " + (lineStart - 1); @@ -223,7 +228,7 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { for (var ix = 0; ix < length; ix++) { var lineEl = simpleDom.createElement("div"); lineEl.className = "ace_line"; - + if (!disableGutter) { var gutterEl = simpleDom.createElement("span"); gutterEl.className ="ace_gutter ace_gutter-cell"; diff --git a/src/incremental_search.js b/src/incremental_search.js index 58ba6725414..8b6a88ea7c5 100644 --- a/src/incremental_search.js +++ b/src/incremental_search.js @@ -68,7 +68,7 @@ class IncrementalSearch extends Search { this.$options.backwards = backwards; editor.keyBinding.addKeyboardHandler(this.$keyboardHandler); // we need to completely intercept paste, just registering an event handler does not work - this.$originalEditorOnPaste = editor.onPaste; + this.$originalEditorOnPaste = editor.onPaste; editor.onPaste = this.onPaste.bind(this); this.$mousedownHandler = editor.on('mousedown', this.onMouseDown.bind(this)); this.selectionFix(editor); @@ -207,6 +207,9 @@ class IncrementalSearch extends Search { }); } + /** + * @internal + */ onMouseDown(evt) { // when mouse interaction happens then we quit incremental search this.deactivate(); @@ -215,6 +218,7 @@ class IncrementalSearch extends Search { /** * @param {string} text + * @internal */ onPaste(text) { this.addString(text); diff --git a/src/keyboard/keybinding.js b/src/keyboard/keybinding.js index 5de3ab8251c..16cff02b4de 100644 --- a/src/keyboard/keybinding.js +++ b/src/keyboard/keybinding.js @@ -85,7 +85,7 @@ class KeyBinding { getKeyboardHandler() { return this.$handlers[this.$handlers.length - 1]; } - + getStatusText() { var data = this.$data; var editor = data.editor; @@ -106,7 +106,7 @@ class KeyBinding { ); if (!toExecute || !toExecute.command) continue; - + // allow keyboardHandler to consume keys if (toExecute.command == "null") { success = true; @@ -115,7 +115,7 @@ class KeyBinding { success = commands.exec(toExecute.command, this.$editor, toExecute.args, e); } // do not stop input events to not break repeating - if (success && e && hashId != -1 && + if (success && e && hashId != -1 && toExecute["passEvent"] != true && toExecute.command["passEvent"] != true ) { event.stopEvent(e); @@ -123,15 +123,15 @@ class KeyBinding { if (success) break; } - + if (!success && hashId == -1) { toExecute = {command: "insertstring"}; success = commands.exec("insertstring", this.$editor, keyString); } - + if (success && this.$editor._signal) this.$editor._signal("keyboardActivity", toExecute); - + return success; } @@ -140,6 +140,7 @@ class KeyBinding { * @param {number} hashId * @param {number} keyCode * @return {boolean} + * @internal */ onCommandKey(e, hashId, keyCode) { var keyString = keyUtil.keyCodeToString(keyCode); @@ -149,6 +150,7 @@ class KeyBinding { /** * @param {string} text * @return {boolean} + * @internal */ onTextInput(text) { return this.$callKeyboardHandlers(-1, text); diff --git a/src/lib/app_config.js b/src/lib/app_config.js index 905998d9f57..85849947896 100644 --- a/src/lib/app_config.js +++ b/src/lib/app_config.js @@ -67,12 +67,12 @@ class AppConfig { messages = defaultEnglishMessages; nlsPlaceholders = "dollarSigns"; } - + /** * @param {Object} obj * @param {string} path * @param {{ [key: string]: any }} options - * @returns {AppConfig} + * @returns {import("../../ace-internal").Ace.AppConfig} */ defineOptions(obj, path, options) { if (!obj.$options) @@ -160,7 +160,7 @@ class AppConfig { if (!messages[defaultString]) { warn("No message found for the default string '" + defaultString + "' in the provided messages. Falling back to the default English message."); } - } + } var translated = messages[key] || messages[defaultString] || defaultString; if (params) { diff --git a/src/lib/lang.js b/src/lib/lang.js index 950fb271a54..857f1525839 100644 --- a/src/lib/lang.js +++ b/src/lib/lang.js @@ -4,6 +4,8 @@ exports.last = function(a) { return a[a.length - 1]; }; + +/** @param {string} string */ exports.stringReverse = function(string) { return string.split("").reverse().join(""); }; @@ -30,8 +32,13 @@ exports.stringTrimLeft = function (string) { exports.stringTrimRight = function (string) { return string.replace(trimEndRegexp, ''); }; - +/** + * @template T + * @param {T} obj + * @return {T} + */ exports.copyObject = function(obj) { + /** @type Object*/ var copy = {}; for (var key in obj) { copy[key] = obj[key]; @@ -44,7 +51,7 @@ exports.copyArray = function(array){ for (var i=0, l=array.length; i 0 && !lineWidgets[first]) first--; - + this.firstRow = config.firstRow; this.lastRow = config.lastRow; @@ -403,16 +404,16 @@ class LineWidgets { if (!w.coverLine) top += config.lineHeight * this.session.getRowLineCount(w.row); w.el.style.top = top - config.offset + "px"; - + var left = w.coverGutter ? 0 : renderer.gutterWidth; if (!w.fixedWidth) left -= renderer.scrollLeft; w.el.style.left = left + "px"; - + if (w.fullWidth && w.screenWidth) { w.el.style.minWidth = config.width + 2 * config.padding + "px"; } - + if (w.fixedWidth) { w.el.style.right = renderer.scrollBar.getWidth() + "px"; } else { @@ -420,7 +421,7 @@ class LineWidgets { } } } - + } diff --git a/src/marker_group.js b/src/marker_group.js index 45304eb7255..2775f843cc1 100644 --- a/src/marker_group.js +++ b/src/marker_group.js @@ -25,7 +25,7 @@ class MarkerGroup { constructor(session, options) { if (options) this.markerType = options.markerType; - + /**@type {import("../ace-internal").Ace.MarkerGroupItem[]}*/ this.markers = []; /**@type {EditSession}*/ this.session = session; @@ -35,8 +35,8 @@ class MarkerGroup { /** * Finds the first marker containing pos - * @param {import("../ace-internal").Ace.Point} pos - * @returns {import("../ace-internal").Ace.MarkerGroupItem | undefined} + * @param {import("../ace-internal").Ace.Point} pos + * @returns {import("../ace-internal").Ace.MarkerGroupItem | undefined} */ getMarkerAtPosition(pos) { return this.markers.find(function(marker) { @@ -46,7 +46,7 @@ class MarkerGroup { /** * Comparator for Array.sort function, which sorts marker definitions by their positions - * + * * @param {MarkerGroupItem} a first marker. * @param {MarkerGroupItem} b second marker. * @returns {number} negative number if a should be before b, positive number if b should be before a, 0 otherwise. diff --git a/src/mode/behaviour.js b/src/mode/behaviour.js index 764843849e3..3a89b28e0e0 100644 --- a/src/mode/behaviour.js +++ b/src/mode/behaviour.js @@ -1,9 +1,5 @@ "use strict"; -/** - * @typedef {Behaviour & {[key: string]: any}} IBehaviour - */ -/**@type {any}*/ var Behaviour; Behaviour = function() { this.$behaviours = {}; @@ -57,7 +53,7 @@ Behaviour = function() { }; /** - * + * * @param [filter] * @returns {{}|*} * @this {Behaviour & this} diff --git a/src/mode/behaviour/css.js b/src/mode/behaviour/css.js index 90acc7653f1..2f05f7919d8 100644 --- a/src/mode/behaviour/css.js +++ b/src/mode/behaviour/css.js @@ -5,6 +5,7 @@ var Behaviour = require("../behaviour").Behaviour; var CstyleBehaviour = require("./cstyle").CstyleBehaviour; var TokenIterator = require("../../token_iterator").TokenIterator; +/**@type {(new() => Partial)}*/ var CssBehaviour = function () { this.inherit(CstyleBehaviour); diff --git a/src/mode/behaviour/cstyle.js b/src/mode/behaviour/cstyle.js index 707fc663879..9af7ce17c9b 100644 --- a/src/mode/behaviour/cstyle.js +++ b/src/mode/behaviour/cstyle.js @@ -47,7 +47,6 @@ var getWrapped = function(selection, selected, opening, closing) { }; /** * Creates a new Cstyle behaviour object with the specified options. - * @constructor * @param {Object} [options] - The options for the Cstyle behaviour object. * @param {boolean} [options.braces] - Whether to force braces auto-pairing. * @param {boolean} [options.closeDocComment] - enables automatic insertion of closing tags for documentation comments. @@ -244,7 +243,7 @@ CstyleBehaviour = function(options) { this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { var quotes = session.$mode.$quotes || defaultQuotes; if (text.length == 1 && quotes[text]) { - if (this.lineCommentStart && this.lineCommentStart.indexOf(text) != -1) + if (this.lineCommentStart && this.lineCommentStart.indexOf(text) != -1) return; initContext(editor); var quote = text; @@ -257,16 +256,16 @@ CstyleBehaviour = function(options) { var line = session.doc.getLine(cursor.row); var leftChar = line.substring(cursor.column-1, cursor.column); var rightChar = line.substring(cursor.column, cursor.column + 1); - + var token = session.getTokenAt(cursor.row, cursor.column); var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); // We're escaped. if (leftChar == "\\" && token && /escape/.test(token.type)) return null; - + var stringBefore = token && /string|escape/.test(token.type); var stringAfter = !rightToken || /string|escape/.test(rightToken.type); - + var pair; if (rightChar == quote) { pair = stringBefore !== stringAfter; @@ -285,7 +284,7 @@ CstyleBehaviour = function(options) { var pairQuotesAfter = session.$mode.$pairQuotesAfter; var shouldPairQuotes = pairQuotesAfter && pairQuotesAfter[quote] && pairQuotesAfter[quote].test(leftChar); - + if ((!shouldPairQuotes && isWordBefore) || isWordAfter) return null; // before or after alphanumeric if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) @@ -317,7 +316,7 @@ CstyleBehaviour = function(options) { } } }); - + if (options.closeDocComment !== false) { this.add("doc comment end", "insertion", function (state, action, editor, session, text) { if (state === "doc-start" && (text === "\n" || text === "\r\n") && editor.selection.isEmpty()) { @@ -349,7 +348,7 @@ CstyleBehaviour = function(options) { // Check for the pattern `*/` followed by `/**` within the token var closeDocPos = currentToken.value.indexOf("*/"); var openDocPos = currentToken.value.indexOf("/**", closeDocPos > - 1 ? closeDocPos + 2 : 0); - + if (openDocPos !== -1 && cursorPosInToken > openDocPos && cursorPosInToken < openDocPos + 3) { return; } @@ -394,7 +393,7 @@ CstyleBehaviour = function(options) { CstyleBehaviour.isSaneInsertion = function(editor, session) { var cursor = editor.getCursorPosition(); var iterator = new TokenIterator(session, cursor.row, cursor.column); - + // Don't insert in the middle of a keyword/identifier/lexical if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { if (/[)}\]]/.test(editor.session.getLine(cursor.row)[cursor.column])) @@ -404,7 +403,7 @@ CstyleBehaviour.isSaneInsertion = function(editor, session) { if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) return false; } - + // Only insert in front of whitespace/comments iterator.stepForward(); return iterator.getCurrentTokenRow() !== cursor.row || diff --git a/src/mode/behaviour/html.js b/src/mode/behaviour/html.js index 23c779cb7d3..da248493a3d 100644 --- a/src/mode/behaviour/html.js +++ b/src/mode/behaviour/html.js @@ -3,6 +3,7 @@ var oop = require("../../lib/oop"); var XmlBehaviour = require("../behaviour/xml").XmlBehaviour; +/**@type {(new() => Partial)}*/ var HtmlBehaviour = function () { XmlBehaviour.call(this); diff --git a/src/mode/behaviour/liquid.js b/src/mode/behaviour/liquid.js index 750278235d0..abbc864ab36 100644 --- a/src/mode/behaviour/liquid.js +++ b/src/mode/behaviour/liquid.js @@ -10,6 +10,7 @@ return token && token.type.lastIndexOf(type + ".xml") > -1; } +/**@type {(new() => Partial)}*/ var LiquidBehaviour = function () { XmlBehaviour.call(this); this.add("autoBraceTagClosing","insertion", function (state, action, editor, session, text) { diff --git a/src/mode/behaviour/xml.js b/src/mode/behaviour/xml.js index dcea0a1f0ee..3b785a695a3 100644 --- a/src/mode/behaviour/xml.js +++ b/src/mode/behaviour/xml.js @@ -8,6 +8,7 @@ function is(token, type) { return token && token.type.lastIndexOf(type + ".xml") > -1; } +/**@type {(new() => Partial)}*/ var XmlBehaviour = function () { this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { @@ -91,7 +92,7 @@ var XmlBehaviour = function () { iterator.stepBackward(); } } - + if (/^\s*>/.test(session.getLine(position.row).slice(position.column))) return; diff --git a/src/mode/behaviour/xquery.js b/src/mode/behaviour/xquery.js index 4d72f38269a..38bd9d399f6 100644 --- a/src/mode/behaviour/xquery.js +++ b/src/mode/behaviour/xquery.js @@ -18,12 +18,13 @@ function hasType(token, type) { }); return hasType; } - + +/**@type {(new() => Partial)}*/ var XQueryBehaviour = function () { - + this.inherit(CstyleBehaviour, ["braces", "parens", "string_dquotes"]); // Get string behaviour this.inherit(XmlBehaviour); // Get xml behaviour - + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { if (text == '>') { var position = editor.getCursorPosition(); diff --git a/src/mode/text.js b/src/mode/text.js index da1ce98c4bb..7bdc201a8ee 100644 --- a/src/mode/text.js +++ b/src/mode/text.js @@ -1,4 +1,8 @@ "use strict"; +/** + * @typedef {import("../../ace-internal").Ace.SyntaxMode} SyntaxMode + */ + var config = require("../config"); var Tokenizer = require("../tokenizer").Tokenizer; @@ -10,7 +14,7 @@ var lang = require("../lib/lang"); var TokenIterator = require("../token_iterator").TokenIterator; var Range = require("../range").Range; -var Mode; +var Mode; Mode = function() { this.HighlightRules = TextHighlightRules; }; @@ -23,7 +27,7 @@ Mode = function() { this.nonTokenRe = new RegExp("^(?:[^" + unicode.wordChars + "\\$_]|\\s])+", "g"); /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.getTokenizer = function() { if (!this.$tokenizer) { @@ -37,7 +41,7 @@ Mode = function() { this.blockComment = ""; /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.toggleCommentLines = function(state, session, startRow, endRow) { var doc = session.doc; @@ -97,7 +101,7 @@ Mode = function() { var lineCommentStart = this.lineCommentStart; } regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?"); - + insertAtTabStop = session.getUseSoftTabs(); var uncomment = function(line, i) { @@ -121,7 +125,7 @@ Mode = function() { var testRemove = function(line, i) { return regexpStart.test(line); }; - + var shouldInsertSpace = function(line, before, after) { var spaces = 0; while (before-- && line.charAt(before) == " ") @@ -170,7 +174,7 @@ Mode = function() { }; /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.toggleBlockComment = function(state, session, range, cursor) { var comment = this.blockComment; @@ -268,14 +272,14 @@ Mode = function() { } } - var delegations = ["toggleBlockComment", "toggleCommentLines", "getNextLineIndent", + var delegations = ["toggleBlockComment", "toggleCommentLines", "getNextLineIndent", "checkOutdent", "autoOutdent", "transformAction", "getCompletions"]; for (let i = 0; i < delegations.length; i++) { (function(scope) { var functionName = delegations[i]; var defaultHandler = scope[functionName]; - scope[delegations[i]] = + scope[delegations[i]] = /** @this {import("../../ace-internal").Ace.SyntaxMode} */ function () { return this.$delegator(functionName, arguments, defaultHandler); @@ -285,7 +289,7 @@ Mode = function() { }; /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.$delegator = function(method, args, defaultHandler) { var state = args[0] || "start"; @@ -298,7 +302,7 @@ Mode = function() { } state = state[0] || "start"; } - + for (var i = 0; i < this.$embeds.length; i++) { if (!this.$modes[this.$embeds[i]]) continue; @@ -314,7 +318,7 @@ Mode = function() { }; /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.transformAction = function(state, action, editor, session, param) { if (this.$behaviour) { @@ -331,7 +335,7 @@ Mode = function() { }; /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.getKeywords = function(append) { // this is for autocompletion to pick up regexp'ed keywords @@ -346,7 +350,7 @@ Mode = function() { completionKeywords.push(ruleItr[r].regex); } else if (typeof ruleItr[r].token === "object") { - for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) { + for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) { if (/keyword|support|storage/.test(ruleItr[r].token[a])) { // drop surrounding parens var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a]; @@ -365,7 +369,7 @@ Mode = function() { }; /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.$createKeywordList = function() { if (!this.$highlightRules) @@ -374,7 +378,7 @@ Mode = function() { }; /** - * @this {import("../../ace-internal").Ace.SyntaxMode} + * @this {SyntaxMode} */ this.getCompletions = function(state, session, pos, prefix) { var keywords = this.$keywordList || this.$createKeywordList(); diff --git a/src/mouse/mouse_handler.js b/src/mouse/mouse_handler.js index 7ec0623020e..3d582b70c48 100644 --- a/src/mouse/mouse_handler.js +++ b/src/mouse/mouse_handler.js @@ -80,7 +80,7 @@ class MouseHandler { } else { renderer.setCursorStyle(""); } - + }, //@ts-expect-error TODO: seems mistyping - should be boolean editor); } @@ -100,7 +100,7 @@ class MouseHandler { } /** - * @param {string} name + * @param {any} name * @param {{ wheelX: number; wheelY: number; }} e */ onMouseWheel(name, e) { @@ -112,7 +112,7 @@ class MouseHandler { this.editor._emit(name, mouseEvent); } - + setState(state) { this.state = state; } @@ -168,7 +168,7 @@ class MouseHandler { var onOperationEnd = function(e) { if (!self.releaseMouse) return; - // some touchpads fire mouseup event after a slight delay, + // some touchpads fire mouseup event after a slight delay, // which can cause problems if user presses a keyboard shortcut quickly if (editor.curOp.command.name && editor.curOp.selectionChanged) { self[self.state + "End"] && self[self.state + "End"](); diff --git a/src/multi_select.js b/src/multi_select.js index 4b03c6decf4..d2a39007522 100644 --- a/src/multi_select.js +++ b/src/multi_select.js @@ -49,7 +49,7 @@ var EditSession = require("./edit_session").EditSession; /**@type {RangeList | null} */ this.rangeList = null; - /** + /** * Adds a range to a selection by entering multiselect mode, if necessary. * @param {Range} range The new range to add * @param {Boolean} $blockChangeEvents Whether or not to block changing events @@ -254,7 +254,7 @@ var EditSession = require("./edit_session").EditSession; /** * Gets list of ranges composing rectangular block on the screen - * + * * @param {ScreenCoordinates} screenCursor The cursor to use * @param {ScreenCoordinates} screenAnchor The anchor to use * @param {Boolean} [includeEmptyLines] If true, this includes ranges inside the block which are empty due to clipping @@ -335,8 +335,8 @@ var EditSession = require("./edit_session").EditSession; var Editor = require("./editor").Editor; (function() { - /** - * + /** + * * Updates the cursor and marker layers. * @method Editor.updateSelectionMarkers * @this {Editor} @@ -346,7 +346,7 @@ var Editor = require("./editor").Editor; this.renderer.updateBackMarkers(); }; - /** + /** * Adds the selection and cursor. * @param {Range & {marker?}} orientedRange A range containing a cursor * @returns {Range & {marker?}} @@ -364,7 +364,7 @@ var Editor = require("./editor").Editor; return orientedRange; }; - /** + /** * Removes the selection marker. * @param {Range & {marker?}} range The selection range added with [[Editor.addSelectionMarker `addSelectionMarker()`]]. * @this {Editor} @@ -478,13 +478,13 @@ var Editor = require("./editor").Editor; return result; }; - /** + /** * Executes a command for each selection range. * @param {any} cmd The command to execute * @param {String} [args] Any arguments for the command * @param {Object|true} [options] * @this {Editor} - **/ + **/ this.forEachSelection = function(cmd, args, options) { if (this.inVirtualSelectionMode) return; @@ -495,10 +495,10 @@ var Editor = require("./editor").Editor; var rangeList = selection.rangeList; var ranges = (keepOrder ? selection : rangeList).ranges; var result; - + if (!ranges.length) return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); - + var reg = selection._eventRegistry; selection._eventRegistry = {}; var tmpSel = new Selection(session); @@ -524,17 +524,17 @@ var Editor = require("./editor").Editor; selection.mergeOverlappingRanges(); if (selection.ranges[0]) selection.fromOrientedRange(selection.ranges[0]); - + var anim = this.renderer.$scrollAnimation; this.onCursorChange(); this.onSelectionChange(); if (anim && anim.from == anim.to) this.renderer.animateScrolling(anim.from); - + return result; }; - /** + /** * Removes all the selections except the last added one. * @this {Editor} **/ @@ -579,7 +579,7 @@ var Editor = require("./editor").Editor; var pos = anchor == this.multiSelect.anchor ? range.cursor == range.start ? range.end : range.start : range.cursor; - if (pos.row != anchor.row + if (pos.row != anchor.row || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); else @@ -593,7 +593,7 @@ var Editor = require("./editor").Editor; * @param {Partial} [options] The search options * @param {Boolean} [additive] keeps * - * @returns {Number} The cumulative count of all found matches + * @returns {Number} The cumulative count of all found matches * @this {Editor} **/ this.findAll = function(needle, options, additive) { @@ -604,9 +604,9 @@ var Editor = require("./editor").Editor; ? this.selection.getWordRange() : this.selection.getRange(); options.needle = this.session.getTextRange(range); - } + } this.$search.set(options); - + var ranges = this.$search.findAll(this.session); if (!ranges.length) return 0; @@ -622,17 +622,17 @@ var Editor = require("./editor").Editor; // keep old selection as primary if possible if (range && selection.rangeList.rangeAtPoint(range.start)) selection.addRange(range, true); - + return ranges.length; }; /** * Adds a cursor above or below the active cursor. - * + * * @param {Number} dir The direction of lines to select: -1 for up, 1 for down * @param {Boolean} [skip] If `true`, removes the active selection range * - * @this {Editor} + * @this {Editor} */ this.selectMoreLines = function(dir, skip) { var range = this.selection.toOrientedRange(); @@ -674,7 +674,7 @@ var Editor = require("./editor").Editor; this.selection.substractPoint(toRemove); }; - /** + /** * Transposes the selected ranges. * @param {Number} dir The direction to rotate selections * @this {Editor} @@ -717,7 +717,7 @@ var Editor = require("./editor").Editor; sel.fromOrientedRange(sel.ranges[0]); }; - /** + /** * Finds the next occurrence of text in an active selection and adds it to the selections. * @param {Number} dir The direction of lines to select: -1 for up, 1 for down * @param {Boolean} [skip] If `true`, removes the active selection range @@ -749,7 +749,7 @@ var Editor = require("./editor").Editor; this.multiSelect.substractPoint(range.cursor); }; - /** + /** * Aligns the cursors or selected text. * @this {Editor} **/ @@ -764,7 +764,7 @@ var Editor = require("./editor").Editor; return true; row = r.cursor.row; }); - + if (!ranges.length || sameRowRanges.length == ranges.length - 1) { var range = this.selection.getRange(); var fr = range.start.row, lr = range.end.row; @@ -778,7 +778,7 @@ var Editor = require("./editor").Editor; do { line = this.session.getLine(fr); } while (/[=:]/.test(line) && --fr > 0); - + if (fr < 0) fr = 0; if (lr >= max) lr = max - 1; } @@ -900,7 +900,7 @@ function isSamePoint(p1, p2) { * patch * adds multicursor support to a session * @this {Editor} - * @type {(e) => void} + * @type {(e: any) => void} */ exports.onSessionChange = function(e) { var session = e.session; diff --git a/src/placeholder.js b/src/placeholder.js index a3e84f76e78..2f3548b54ef 100644 --- a/src/placeholder.js +++ b/src/placeholder.js @@ -6,7 +6,7 @@ var Range = require("./range").Range; var EventEmitter = require("./lib/event_emitter").EventEmitter; var oop = require("./lib/oop"); -class PlaceHolder { +class PlaceHolder { /** * @param {EditSession} session * @param {Number} length @@ -51,7 +51,7 @@ class PlaceHolder { var _self = this; var doc = this.doc; var session = this.session; - + this.selectionBefore = session.selection.toJSON(); if (session.selection.inMultiSelectMode) session.selection.toSingleRange(); @@ -70,7 +70,7 @@ class PlaceHolder { }); session.setUndoSelect(false); } - + /** * PlaceHolder.showOtherMarkers() * @@ -86,7 +86,7 @@ class PlaceHolder { anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false); }); } - + /** * PlaceHolder.hideOtherMarkers() * @@ -103,14 +103,15 @@ class PlaceHolder { /** * PlaceHolder@onUpdate(e) - * + * * Emitted when the place holder updates. * @param {import("../ace-internal").Ace.Delta} delta + * @internal */ onUpdate(delta) { if (this.$updating) return this.updateAnchors(delta); - + var range = delta; if (range.start.row !== range.end.row) return; if (range.start.row !== this.pos.row) return; @@ -118,9 +119,9 @@ class PlaceHolder { var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column; var inMainRange = range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1; var distanceFromStart = range.start.column - this.pos.column; - + this.updateAnchors(delta); - + if (inMainRange) this.length += lengthDiff; @@ -139,7 +140,7 @@ class PlaceHolder { } } } - + this.$updating = false; this.updateMarkers(); } @@ -153,7 +154,7 @@ class PlaceHolder { this.others[i].onChange(delta); this.updateMarkers(); } - + updateMarkers() { if (this.$updating) return; @@ -171,9 +172,10 @@ class PlaceHolder { /** * PlaceHolder@onCursorChange(e) - * + * * Emitted when the cursor changes. * @param {any} [event] + * @internal */ onCursorChange(event) { if (this.$updating || !this.session) return; @@ -186,13 +188,13 @@ class PlaceHolder { this._emit("cursorLeave", event); } } - + /** * PlaceHolder.detach() - * + * * TODO * - **/ + **/ detach() { this.session.removeMarker(this.pos && this.pos.markerId); this.hideOtherMarkers(); @@ -201,10 +203,10 @@ class PlaceHolder { this.session.setUndoSelect(true); this.session = null; } - + /** * PlaceHolder.cancel() - * + * * TODO * **/ diff --git a/src/scrollbar.js b/src/scrollbar.js index 70cc2cc02af..877978a493b 100644 --- a/src/scrollbar.js +++ b/src/scrollbar.js @@ -37,7 +37,7 @@ class Scrollbar { event.addListener(this.element, "scroll", this.onScroll.bind(this)); event.addListener(this.element, "mousedown", event.preventDefault); } - + setVisible(isVisible) { this.element.style.display = isVisible ? "" : "none"; this.isVisible = isVisible; @@ -64,18 +64,19 @@ class VScrollBar extends Scrollbar { // element to show the scrollbar but still pretend that the scrollbar has a width // of 0px // in Firefox 6+ scrollbar is hidden if element has the same width as scrollbar - // make element a little bit wider to retain scrollbar when page is zoomed + // make element a little bit wider to retain scrollbar when page is zoomed renderer.$scrollbarWidth = this.width = dom.scrollbarWidth(parent.ownerDocument); this.inner.style.width = this.element.style.width = (this.width || 15) + 5 + "px"; this.$minWidth = 0; } - + /** * Emitted when the scroll bar, well, scrolls. * @event scroll + * @internal **/ onScroll() { @@ -105,7 +106,7 @@ class VScrollBar extends Scrollbar { setHeight(height) { this.element.style.height = height + "px"; } - + /** * Sets the scroll height of the scroll bar, in pixels. * @param {Number} height The new scroll height @@ -162,15 +163,16 @@ class HScrollBar extends Scrollbar { // element to show the scrollbar but still pretend that the scrollbar has a width // of 0px // in Firefox 6+ scrollbar is hidden if element has the same width as scrollbar - // make element a little bit wider to retain scrollbar when page is zoomed + // make element a little bit wider to retain scrollbar when page is zoomed this.height = renderer.$scrollbarWidth; this.inner.style.height = this.element.style.height = (this.height || 15) + 5 + "px"; } - + /** * Emitted when the scroll bar, well, scrolls. * @event scroll + * @internal **/ onScroll() { if (!this.skipEvent) { diff --git a/src/scrollbar_custom.js b/src/scrollbar_custom.js index 095d2038ba8..1f261175851 100644 --- a/src/scrollbar_custom.js +++ b/src/scrollbar_custom.js @@ -91,7 +91,7 @@ oop.implement(ScrollBar.prototype, EventEmitter); * @constructor **/ class VScrollBar extends ScrollBar { - + constructor(parent, renderer) { super(parent, '-v'); this.scrollTop = 0; @@ -102,9 +102,10 @@ class VScrollBar extends ScrollBar { this.inner.style.width = this.element.style.width = (this.width || 15) + "px"; this.$minWidth = 0; } - + /** * Emitted when the scroll thumb dragged or scrollbar canvas clicked. + * @internal **/ onMouseDown(eType, e) { if (eType !== "mousedown") return; @@ -238,9 +239,10 @@ class HScrollBar extends ScrollBar { this.inner.style.height = this.element.style.height = (this.height || 12) + "px"; this.renderer = renderer; } - + /** * Emitted when the scroll thumb dragged or scrollbar canvas clicked. + * @internal **/ onMouseDown(eType, e) { if (eType !== "mousedown") return; diff --git a/src/search.js b/src/search.js index b19bd87ef50..17a7c63222d 100644 --- a/src/search.js +++ b/src/search.js @@ -1,6 +1,7 @@ "use strict"; /** * @typedef {import("./edit_session").EditSession} EditSession + * @typedef {import("../ace-internal").Ace.SearchOptions} SearchOptions */ var lang = require("./lib/lang"); var oop = require("./lib/oop"); @@ -10,34 +11,15 @@ var Range = require("./range").Range; * A class designed to handle all sorts of text searches within a [[Document `Document`]]. **/ class Search { - /** - * Creates a new `Search` object. The following search options are available: - * @typedef SearchOptions - * - * @property {string|RegExp} [needle] - The string or regular expression you're looking for - * @property {boolean} [backwards] - Whether to search backwards from where cursor currently is - * @property {boolean} [wrap] - Whether to wrap the search back to the beginning when it hits the end - * @property {boolean} [caseSensitive] - Whether the search ought to be case-sensitive - * @property {boolean} [wholeWord] - Whether the search matches only on whole words - * @property {Range|null} [range] - The [[Range]] to search within. Set this to `null` for the whole document - * @property {boolean} [regExp] - Whether the search is a regular expression or not - * @property {Range|import("../ace-internal").Ace.Position} [start] - The starting [[Range]] or cursor position to begin the search - * @property {boolean} [skipCurrent] - Whether or not to include the current line in the search - * @property {boolean} [$isMultiLine] - true, if needle has \n or \r\n - * @property {boolean} [preserveCase] - * @property {boolean} [preventScroll] - * @property {boolean} [$supportsUnicodeFlag] - internal property, determine if browser supports unicode flag - * @property {any} [re] - **/ - + constructor() { - /**@type {SearchOptions}*/ + /**@type {Partial}*/ this.$options = {}; } - + /** * Sets the search options via the `options` parameter. - * @param {Partial} options An object containing all the new search properties + * @param {Partial} options An object containing all the new search properties * @returns {Search} * @chainable **/ @@ -48,15 +30,15 @@ class Search { /** * [Returns an object containing all the search options.]{: #Search.getOptions} - * @returns {Partial} + * @returns {Partial} **/ getOptions() { return lang.copyObject(this.$options); } - + /** * Sets the search options via the `options` parameter. - * @param {SearchOptions} options object containing all the search propertie + * @param {Partial} options object containing all the search propertie * @related Search.set **/ setOptions(options) { @@ -83,7 +65,7 @@ class Search { firstRange = null; return false; } - + return true; }); @@ -116,12 +98,12 @@ class Search { for (var j = 0; j < len; j++) if (lines[row + j].search(re[j]) == -1) continue outer; - + var startLine = lines[row]; var line = lines[row + len - 1]; var startIndex = startLine.length - startLine.match(re[0])[0].length; var endIndex = line.match(re[len - 1])[0].length; - + if (prevRange && prevRange.end.row === row && prevRange.end.column > startIndex ) { @@ -153,7 +135,7 @@ class Search { var endRow = range.end.row - range.start.row; while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == endRow) j--; - + ranges = ranges.slice(i, j + 1); for (i = 0, j = ranges.length; i < j; i++) { ranges[i].start.row += range.start.row; @@ -171,7 +153,7 @@ class Search { * + (String): If `options.regExp` is `true`, this function returns `input` with the replacement already made. Otherwise, this function just returns `replacement`.
* If `options.needle` was not found, this function returns `null`. * - * + * * @returns {String} **/ replace(input, replacement) { @@ -190,7 +172,7 @@ class Search { if (!options.regExp) { replacement = replacement.replace(/\$/g, "$$$$"); } - + replacement = input.replace(re, replacement); if (options.preserveCase) { replacement = replacement.split(""); @@ -203,20 +185,20 @@ class Search { } replacement = replacement.join(""); } - + return replacement; } /** - * - * @param {SearchOptions} options + * + * @param {Partial} options * @param {boolean} [$disableFakeMultiline] * @return {RegExp|boolean|*[]|*} */ $assembleRegExp(options, $disableFakeMultiline) { if (options.needle instanceof RegExp) return options.re = options.needle; - + var needle = options.needle; if (!options.needle) @@ -237,7 +219,7 @@ class Search { if (options.wholeWord) needle = addWordBoundary(needle, options); - + options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle); if (options.$isMultiLine) return options.re = this.$assembleMultilineRegExp(needle, modifier); @@ -281,13 +263,13 @@ class Search { var start = options.start; if (!start) start = range ? range[backwards ? "end" : "start"] : session.selection.getRange(); - + if (start.start) start = start[skipCurrent != backwards ? "end" : "start"]; var firstRow = range ? range.start.row : 0; var lastRow = range ? range.end.row : session.getLength() - 1; - + if (backwards) { var forEach = function(callback) { var row = start.row; @@ -318,7 +300,7 @@ class Search { return; }; } - + if (options.$isMultiLine) { var len = re.length; var forEachInLine = function(row, offset, callback) { @@ -387,9 +369,9 @@ class Search { } /** - * + * * @param {string} needle - * @param {SearchOptions} options + * @param {Partial} options * @return {string} */ function addWordBoundary(needle, options) { diff --git a/src/snippets.js b/src/snippets.js index 263434e0f67..6b7b53abfe8 100644 --- a/src/snippets.js +++ b/src/snippets.js @@ -119,7 +119,7 @@ class SnippetManager { getTokenizer() { return SnippetManager["$tokenizer"] || this.createTokenizer(); } - + createTokenizer() { function TabstopToken(str) { str = str.substr(1); @@ -131,7 +131,7 @@ class SnippetManager { return "(?:[^\\\\" + ch + "]|\\\\.)"; } var formatMatcher = { - regex: "/(" + escape("/") + "+)/", + regex: "/(" + escape("/") + "+)/", onMatch: function(val, state, stack) { var ts = stack[0]; ts.fmtString = true; @@ -141,7 +141,7 @@ class SnippetManager { }, next: "formatString" }; - + SnippetManager["$tokenizer"] = new Tokenizer({ start: [ {regex: /\\./, onMatch: function(val, state, stack) { @@ -246,13 +246,13 @@ class SnippetManager { return x.value || x; }); } - + getVariableValue(editor, name, indentation) { if (/^\d+$/.test(name)) return (this.variables.__ || {})[name] || ""; if (/^[A-Z]\d+$/.test(name)) return (this.variables[name[0] + "__"] || {})[name.substr(1)] || ""; - + name = name.replace(/^TM_/, ""); if (!this.variables.hasOwnProperty(name)) return ""; @@ -261,7 +261,7 @@ class SnippetManager { value = this.variables[name](editor, name, indentation); return value == null ? "" : value; } - + // returns string formatted according to http://manual.macromates.com/en/regular_expressions#replacement_string_syntax_format_strings tmStrFormat(str, ch, editor) { if (!ch.fmt) return str; @@ -302,7 +302,7 @@ class SnippetManager { }); return formatted; } - + tmFormatFunction(str, ch, editor) { if (ch.formatFunction == "upcase") return str.toUpperCase(); @@ -331,21 +331,21 @@ class SnippetManager { } if (!ch) continue; afterNewLine = false; - + if (ch.fmtString) { var j = snippet.indexOf(ch, i + 1); if (j == -1) j = snippet.length; ch.fmt = snippet.slice(i + 1, j); i = j; } - + if (ch.text) { var value = this.getVariableValue(editor, ch.text, indentation) + ""; if (ch.fmtString) value = this.tmStrFormat(value, ch, editor); if (ch.formatFunction) value = this.tmFormatFunction(value, ch, editor); - + if (value && !ch.ifEnd) { result.push(value); gotoNext(ch); @@ -375,7 +375,7 @@ class SnippetManager { insertSnippetForSelection(editor, snippetText, options={}) { var processedSnippet = processSnippetText.call(this, editor, snippetText, options); - + var range = editor.getSelectionRange(); var end = editor.session.replace(range, processedSnippet.text); @@ -388,11 +388,11 @@ class SnippetManager { var self = this; if (editor.inVirtualSelectionMode) return self.insertSnippetForSelection(editor, snippetText, options); - + editor.forEachSelection(function() { self.insertSnippetForSelection(editor, snippetText, options); }, null, {keepOrder: true}); - + if (editor.tabstopManager) editor.tabstopManager.tabNext(); } @@ -402,7 +402,7 @@ class SnippetManager { scope = scope.split("/").pop(); if (scope === "html" || scope === "php") { // PHP is actually HTML - if (scope === "php" && !editor.session.$mode.inlinePhp) + if (scope === "php" && !editor.session.$mode.inlinePhp) scope = "html"; var c = editor.getCursorPosition(); var state = editor.session.getState(c.row); @@ -418,7 +418,7 @@ class SnippetManager { scope = "php"; } } - + return scope; } @@ -442,7 +442,7 @@ class SnippetManager { editor.tabstopManager.tabNext(); return result; } - + expandSnippetForSelection(editor, options) { var cursor = editor.getCursorPosition(); var line = editor.session.getLine(cursor.row); @@ -508,10 +508,10 @@ class SnippetManager { var snippetMap = this.snippetMap; var snippetNameMap = this.snippetNameMap; var self = this; - - if (!snippets) + + if (!snippets) snippets = []; - + function wrapRegexp(src) { if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src)) src = "(?:" + src + ")"; @@ -562,10 +562,10 @@ class SnippetManager { s.guard = "\\b"; s.trigger = lang.escapeRegExp(s.tabTrigger); } - + if (!s.trigger && !s.guard && !s.endTrigger && !s.endGuard) return; - + s.startRe = guardedRegexp(s.trigger, s.guard, true); s.triggerRe = new RegExp(s.trigger); @@ -657,7 +657,7 @@ var processSnippetText = function(editor, snippetText, options={}) { var line = editor.session.getLine(cursor.row); var tabString = editor.session.getTabString(); var indentString = line.match(/^\s*/)[0]; - + if (cursor.column < indentString.length) indentString = indentString.slice(0, cursor.column); @@ -749,7 +749,7 @@ var processSnippetText = function(editor, snippetText, options={}) { if (ts.indexOf(p) === -1) ts.push(p); } - + // convert to plain text var row = 0, column = 0; var text = ""; @@ -818,7 +818,9 @@ class TabstopManager { this.session = null; this.editor = null; } - + /** + * @internal + */ onChange(delta) { var isRemove = delta.action[0] == "r"; var selectedTabstop = this.selectedTabstop || {}; @@ -828,7 +830,7 @@ class TabstopManager { var ts = tabstops[i]; var active = ts == selectedTabstop || parents[ts.index]; ts.rangeList.$bias = active ? 0 : 1; - + if (delta.action == "remove" && ts !== selectedTabstop) { var parentActive = ts.parents && ts.parents[selectedTabstop.index]; var startIndex = ts.rangeList.pointIndex(delta.start, parentActive); @@ -862,10 +864,16 @@ class TabstopManager { } this.$inChange = false; } + /** + * @internal + */ onAfterExec(e) { if (e.command && !e.command.readOnly) this.updateLinkedFields(); } + /** + * @internal + */ onChangeSelection() { if (!this.editor) return; @@ -882,6 +890,9 @@ class TabstopManager { } this.detach(); } + /** + * @internal + */ onChangeSession() { this.detach(); } @@ -906,7 +917,7 @@ class TabstopManager { ts = this.tabstops[this.index]; if (!ts || !ts.length) return; - + this.selectedTabstop = ts; var range = ts.firstNonLinked || ts; if (ts.choices) range.cursor = range.start; @@ -921,14 +932,14 @@ class TabstopManager { } else { this.editor.selection.fromOrientedRange(range); } - + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); if (this.selectedTabstop && this.selectedTabstop.choices) this.editor.execCommand("startAutocomplete", {matches: this.selectedTabstop.choices}); } addTabstops(tabstops, start, end) { var useLink = this.useLink || !this.editor.getOption("enableMultiselect"); - + if (!this.$openTabstops) this.$openTabstops = []; // add final tabstop if missing @@ -977,7 +988,7 @@ class TabstopManager { dest.rangeList.$bias = 0; dest.rangeList.addList(dest); }, this); - + if (arg.length > 2) { // when adding new snippet inside existing one, make sure 0 tabstop is at the end if (this.tabstops.length) diff --git a/src/tooltip.js b/src/tooltip.js index fc62ae7a52a..f0f69951739 100644 --- a/src/tooltip.js +++ b/src/tooltip.js @@ -21,7 +21,7 @@ class Tooltip { this.$element = null; this.$parentNode = parentNode; } - + $init() { this.$element = dom.createElement("div"); this.$element.className = CLASSNAME; @@ -112,7 +112,7 @@ class Tooltip { getWidth() { return this.getElement().offsetWidth; } - + destroy() { this.isOpen = false; if (this.$element && this.$element.parentNode) { @@ -160,7 +160,7 @@ class PopupManager { break; } } - + if (shouldDisplay) { visiblepopups.push(popup); } else { @@ -192,23 +192,23 @@ exports.Tooltip = Tooltip; class HoverTooltip extends Tooltip { constructor(parentNode=document.body) { super(parentNode); - + this.timeout = undefined; this.lastT = 0; this.idleTime = 350; this.lastEvent = undefined; - + this.onMouseOut = this.onMouseOut.bind(this); this.onMouseMove = this.onMouseMove.bind(this); this.waitForHover = this.waitForHover.bind(this); this.hide = this.hide.bind(this); - + var el = this.getElement(); el.style.whiteSpace = "pre-wrap"; el.style.pointerEvents = "auto"; el.addEventListener("mouseout", this.onMouseOut); el.tabIndex = -1; - + el.addEventListener("blur", function() { if (!el.contains(document.activeElement)) this.hide(); }.bind(this)); @@ -241,6 +241,7 @@ class HoverTooltip extends Tooltip { /** * @param {MouseEvent} e * @param {Editor} editor + * @internal */ onMouseMove(e, editor) { this.lastEvent = e; @@ -249,7 +250,7 @@ class HoverTooltip extends Tooltip { if (this.isOpen) { var pos = this.lastEvent && this.lastEvent.getDocumentPosition(); if ( - !this.range + !this.range || !this.range.contains(pos.row, pos.column) || isMousePressed || this.isOutsideOfText(this.lastEvent) @@ -268,7 +269,7 @@ class HoverTooltip extends Tooltip { this.timeout = setTimeout(this.waitForHover, this.idleTime - dt); return; } - + this.timeout = null; if (this.lastEvent && !this.isOutsideOfText(this.lastEvent)) { this.$gatherData(this.lastEvent, this.lastEvent.editor); @@ -296,7 +297,7 @@ class HoverTooltip extends Tooltip { } /** - * @param {any} value + * @param {(event: MouseEvent, editor: Editor) => void} value */ setDataProvider(value) { this.$gatherData = value; @@ -305,14 +306,14 @@ class HoverTooltip extends Tooltip { /** * @param {Editor} editor * @param {Range} range - * @param {any} domNode + * @param {HTMLElement} domNode * @param {MouseEvent} startingEvent */ showForRange(editor, range, domNode, startingEvent) { var MARGIN = 10; if (startingEvent && startingEvent != this.lastEvent) return; if (this.isOpen && document.activeElement == this.getElement()) return; - + var renderer = editor.renderer; if (!this.isOpen) { popupManager.addPopup(this); @@ -320,23 +321,23 @@ class HoverTooltip extends Tooltip { this.setTheme(renderer.theme); } this.isOpen = true; - + this.addMarker(range, editor.session); this.range = Range.fromPoints(range.start, range.end); var position = renderer.textToScreenCoordinates(range.start.row, range.start.column); - + var rect = renderer.scroller.getBoundingClientRect(); // clip position to visible area of the editor if (position.pageX < rect.left) position.pageX = rect.left; - + var element = this.getElement(); element.innerHTML = ""; element.appendChild(domNode); - + element.style.maxHeight = ""; - element.style.display = "block"; - + element.style.display = "block"; + // measure the size of tooltip, without constraints on its height var labelHeight = element.clientHeight; var labelWidth = element.clientWidth; @@ -347,11 +348,11 @@ class HoverTooltip extends Tooltip { if (position.pageY - labelHeight < 0 && position.pageY < spaceBelow) { isAbove = false; } - + element.style.maxHeight = (isAbove ? position.pageY : spaceBelow) - MARGIN + "px"; element.style.top = isAbove ? "" : position.pageY + renderer.lineHeight + "px"; element.style.bottom = isAbove ? window.innerHeight - position.pageY + "px" : ""; - + // try to align tooltip left with the range, but keep it on screen element.style.left = Math.min(position.pageX, window.innerWidth - labelWidth - MARGIN) + "px"; } @@ -367,7 +368,7 @@ class HoverTooltip extends Tooltip { this.$markerSession = session; this.marker = session && session.addMarker(range, "ace_highlight-marker", "text"); } - + hide(e) { if (!e && document.activeElement == this.getElement()) return; @@ -397,6 +398,9 @@ class HoverTooltip extends Tooltip { window.removeEventListener("mousedown", this.hide, true); } + /** + * @internal + */ onMouseOut(e) { if (this.timeout) { clearTimeout(this.timeout); diff --git a/src/virtual_renderer.js b/src/virtual_renderer.js index 7c0a7fc2d06..6efa58d7d6b 100644 --- a/src/virtual_renderer.js +++ b/src/virtual_renderer.js @@ -29,14 +29,14 @@ dom.importCssString(editorCss, "ace_editor.css", false); /** * The class that is responsible for drawing everything you see on the screen! - * @related editor.renderer + * @related editor.renderer **/ class VirtualRenderer { /** * Constructs a new `VirtualRenderer` within the `container` specified, applying the given `theme`. * @param {HTMLElement | null} [container] The root element of the editor * @param {String} [theme] The starting theme - + **/ constructor(container, theme) { var _self = this; @@ -204,7 +204,7 @@ class VirtualRenderer { setSession(session) { if (this.session) this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode); - + this.session = session; if (session && this.scrollMargin.top && session.getScrollTop() <= 0) session.setScrollTop(-this.scrollMargin.top); @@ -216,11 +216,11 @@ class VirtualRenderer { this.$textLayer.setSession(session); if (!session) return; - + this.$loop.schedule(this.CHANGE_FULL); this.session.$setFontMetrics(this.$fontMetrics); this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null; - + this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this); this.onChangeNewLineMode(); this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode); @@ -265,12 +265,18 @@ class VirtualRenderer { this.$loop.schedule(this.CHANGE_LINES); } + /** + * @internal + */ onChangeNewLineMode() { this.$loop.schedule(this.CHANGE_TEXT); this.$textLayer.$updateEolChar(); this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR); } - + + /** + * @internal + */ onChangeTabSize() { this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER); this.$textLayer.onChangeTabSize(); @@ -286,7 +292,7 @@ class VirtualRenderer { /** * Triggers a full update of all the layers, for all the rows. * @param {Boolean} [force] If `true`, forces the changes through - + **/ updateFull(force) { if (force) @@ -314,7 +320,7 @@ class VirtualRenderer { * @param {Number} [gutterWidth] The width of the gutter in pixels * @param {Number} [width] The width of the editor in pixels * @param {Number} [height] The hiehgt of the editor, in pixels - + * @internal **/ onResize(force, gutterWidth, width, height) { if (this.resizing > 2) @@ -341,7 +347,7 @@ class VirtualRenderer { var changes = this.$updateCachedSize(force, gutterWidth, width, height); if (this.$resizeTimer) this.$resizeTimer.cancel(); - + if (!this.$size.scrollerHeight || (!width && !height)) return this.resizing = 0; @@ -369,7 +375,7 @@ class VirtualRenderer { * @param [width] * @param [height] * @return {number} - + */ $updateCachedSize(force, gutterWidth, width, height) { height -= (this.$extraHeight || 0); @@ -388,7 +394,7 @@ class VirtualRenderer { size.scrollerHeight = size.height; if (this.$horizScroll) size.scrollerHeight -= this.scrollBarH.getHeight(); - + this.scrollBarV.setHeight(size.scrollerHeight); this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px"; @@ -398,29 +404,29 @@ class VirtualRenderer { if (width && (force || size.width != width)) { changes |= this.CHANGE_SIZE; size.width = width; - + if (gutterWidth == null) gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; - + this.gutterWidth = gutterWidth; - + dom.setStyle(this.scrollBarH.element.style, "left", gutterWidth + "px"); dom.setStyle(this.scroller.style, "left", gutterWidth + this.margin.left + "px"); size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth() - this.margin.h); dom.setStyle(this.$gutter.style, "left", this.margin.left + "px"); - + var right = this.scrollBarV.getWidth() + "px"; dom.setStyle(this.scrollBarH.element.style, "right", right); dom.setStyle(this.scroller.style, "right", right); dom.setStyle(this.scroller.style, "bottom", this.scrollBarH.getHeight()); - + this.scrollBarH.setWidth(size.scrollerWidth); if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force) { changes |= this.CHANGE_FULL; } } - + size.$dirty = !width || !height; if (changes) @@ -430,9 +436,9 @@ class VirtualRenderer { } /** - * + * * @param {number} width - + * @internal */ onGutterResize(width) { var gutterWidth = this.$showGutter ? width : 0; @@ -450,7 +456,7 @@ class VirtualRenderer { /** * Adjusts the wrap limit, which is the number of characters that can fit within the width of the edit area on screen. - + **/ adjustWrapLimit() { var availableWidth = this.$size.scrollerWidth - this.$padding * 2; @@ -461,7 +467,7 @@ class VirtualRenderer { /** * Identifies whether you want to have an animated scroll or not. * @param {Boolean} shouldAnimate Set to `true` to show animated scrolls - + **/ setAnimatedScroll(shouldAnimate){ this.setOption("animatedScroll", shouldAnimate); @@ -470,7 +476,7 @@ class VirtualRenderer { /** * Returns whether an animated scroll happens or not. * @returns {Boolean} - + **/ getAnimatedScroll() { return this.$animatedScroll; @@ -479,7 +485,7 @@ class VirtualRenderer { /** * Identifies whether you want to show invisible characters or not. * @param {Boolean} showInvisibles Set to `true` to show invisibles - + **/ setShowInvisibles(showInvisibles) { this.setOption("showInvisibles", showInvisibles); @@ -489,7 +495,7 @@ class VirtualRenderer { /** * Returns whether invisible characters are being shown or not. * @returns {Boolean} - + **/ getShowInvisibles() { return this.getOption("showInvisibles"); @@ -497,7 +503,7 @@ class VirtualRenderer { /** * @return {boolean} - + */ getDisplayIndentGuides() { return this.getOption("displayIndentGuides"); @@ -505,14 +511,14 @@ class VirtualRenderer { /** * @param {boolean} display - + */ setDisplayIndentGuides(display) { this.setOption("displayIndentGuides", display); } /** - + * @return {boolean} */ getHighlightIndentGuides() { @@ -520,7 +526,7 @@ class VirtualRenderer { } /** - + * @param {boolean} highlight */ setHighlightIndentGuides(highlight) { @@ -530,7 +536,7 @@ class VirtualRenderer { /** * Identifies whether you want to show the print margin or not. * @param {Boolean} showPrintMargin Set to `true` to show the print margin - + **/ setShowPrintMargin(showPrintMargin) { this.setOption("showPrintMargin", showPrintMargin); @@ -539,7 +545,7 @@ class VirtualRenderer { /** * Returns whether the print margin is being shown or not. * @returns {Boolean} - + **/ getShowPrintMargin() { return this.getOption("showPrintMargin"); @@ -547,7 +553,7 @@ class VirtualRenderer { /** * Identifies whether you want to show the print margin column or not. * @param {number} printMarginColumn Set to `true` to show the print margin column - + **/ setPrintMarginColumn(printMarginColumn) { this.setOption("printMarginColumn", printMarginColumn); @@ -556,7 +562,7 @@ class VirtualRenderer { /** * Returns whether the print margin column is being shown or not. * @returns {number} - + **/ getPrintMarginColumn() { return this.getOption("printMarginColumn"); @@ -565,7 +571,7 @@ class VirtualRenderer { /** * Returns `true` if the gutter is being shown. * @returns {Boolean} - + **/ getShowGutter(){ return this.getOption("showGutter"); @@ -574,14 +580,14 @@ class VirtualRenderer { /** * Identifies whether you want to show the gutter or not. * @param {Boolean} show Set to `true` to show the gutter - + **/ setShowGutter(show){ return this.setOption("showGutter", show); } /** - + * @returns {boolean} */ getFadeFoldWidgets(){ @@ -589,7 +595,7 @@ class VirtualRenderer { } /** - + * @param {boolean} show */ setFadeFoldWidgets(show) { @@ -605,7 +611,7 @@ class VirtualRenderer { } /** - + * @returns {boolean} */ getHighlightGutterLine() { @@ -613,7 +619,7 @@ class VirtualRenderer { } /** - + */ $updatePrintMargin() { if (!this.$showPrintMargin && !this.$printMarginEl) @@ -631,7 +637,7 @@ class VirtualRenderer { var style = this.$printMarginEl.style; style.left = Math.round(this.characterWidth * this.$printMarginColumn + this.$padding) + "px"; style.visibility = this.$showPrintMargin ? "visible" : "hidden"; - + if (this.session && this.session.$wrap == -1) this.adjustWrapLimit(); } @@ -666,7 +672,7 @@ class VirtualRenderer { // move text input over the cursor // this is required for IME /** - + */ $moveTextAreaToCursor() { if (this.$isMousePressed) return; @@ -681,7 +687,7 @@ class VirtualRenderer { return; if (composition && composition.markerRange) pixelPos = this.$cursorLayer.getPixelPosition(composition.markerRange.start, true); - + var config = this.layerConfig; var posTop = pixelPos.top; var posLeft = pixelPos.left; @@ -707,7 +713,7 @@ class VirtualRenderer { posTop += this.lineHeight + 2; } } - + posLeft -= this.scrollLeft; if (posLeft > this.$size.scrollerWidth - w) posLeft = this.$size.scrollerWidth - w; @@ -762,7 +768,7 @@ class VirtualRenderer { /** * Sets the padding for all the layers. * @param {Number} padding A new padding value (in pixels) - + **/ setPadding(padding) { this.$padding = padding; @@ -775,12 +781,12 @@ class VirtualRenderer { } /** - * + * * @param {number} [top] * @param {number} [bottom] * @param {number} [left] * @param {number} [right] - + */ setScrollMargin(top, bottom, left, right) { var sm = this.scrollMargin; @@ -801,7 +807,7 @@ class VirtualRenderer { * @param {number} [bottom] * @param {number} [left] * @param {number} [right] - + */ setMargin(top, bottom, left, right) { var sm = this.margin; @@ -818,7 +824,7 @@ class VirtualRenderer { /** * Returns whether the horizontal scrollbar is set to be always visible. * @returns {Boolean} - + **/ getHScrollBarAlwaysVisible() { return this.$hScrollBarAlwaysVisible; @@ -827,7 +833,7 @@ class VirtualRenderer { /** * Identifies whether you want to show the horizontal scrollbar or not. * @param {Boolean} alwaysVisible Set to `true` to make the horizontal scroll bar visible - + **/ setHScrollBarAlwaysVisible(alwaysVisible) { this.setOption("hScrollBarAlwaysVisible", alwaysVisible); @@ -835,7 +841,7 @@ class VirtualRenderer { /** * Returns whether the horizontal scrollbar is set to be always visible. * @returns {Boolean} - + **/ getVScrollBarAlwaysVisible() { return this.$vScrollBarAlwaysVisible; @@ -850,7 +856,7 @@ class VirtualRenderer { } /** - + */ $updateScrollBarV() { var scrollHeight = this.layerConfig.maxHeight; @@ -873,17 +879,17 @@ class VirtualRenderer { freeze() { this.$frozen = true; } - + unfreeze() { this.$frozen = false; } /** - * + * * @param {number} changes * @param {boolean} [force] * @returns {number} - + */ $renderChanges(changes, force) { if (this.$changes) { @@ -892,8 +898,8 @@ class VirtualRenderer { } if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) { this.$changes |= changes; - return; - } + return; + } if (this.$size.$dirty) { this.$changes |= changes; return this.onResize(true); @@ -902,9 +908,9 @@ class VirtualRenderer { this.$textLayer.checkForSizeChanges(); } // this.$logChanges(changes); - + this._signal("beforeRender", changes); - + if (this.session && this.session.$bidiHandler) this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics); @@ -920,7 +926,7 @@ class VirtualRenderer { changes |= this.$computeLayerConfig() | this.$loop.clear(); // If a change is made offscreen and wrapMode is on, then the onscreen // lines may have been pushed down. If so, the first screen row will not - // have changed, but the first actual row will. In that case, adjust + // have changed, but the first actual row will. In that case, adjust // scrollTop so that the cursor and onscreen content stays in the same place. // TODO: find a better way to handle this, that works non wrapped case and doesn't compute layerConfig twice if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) { @@ -937,16 +943,16 @@ class VirtualRenderer { this.$updateScrollBarV(); if (changes & this.CHANGE_H_SCROLL) this.$updateScrollBarH(); - + dom.translate(this.content, -this.scrollLeft, -config.offset); - + var width = config.width + 2 * this.$padding + "px"; var height = config.minHeight + "px"; - + dom.setStyle(this.content.style, "width", width); dom.setStyle(this.content.style, "height", height); } - + // horizontal scrolling if (changes & this.CHANGE_H_SCROLL) { dom.translate(this.content, -this.scrollLeft, -config.offset); @@ -1046,53 +1052,53 @@ class VirtualRenderer { } /** - + */ $autosize() { var height = this.session.getScreenLength() * this.lineHeight; var maxHeight = this.$maxLines * this.lineHeight; - var desiredHeight = Math.min(maxHeight, + var desiredHeight = Math.min(maxHeight, Math.max((this.$minLines || 1) * this.lineHeight, height) ) + this.scrollMargin.v + (this.$extraHeight || 0); if (this.$horizScroll) desiredHeight += this.scrollBarH.getHeight(); if (this.$maxPixelHeight && desiredHeight > this.$maxPixelHeight) desiredHeight = this.$maxPixelHeight; - + var hideScrollbars = desiredHeight <= 2 * this.lineHeight; var vScroll = !hideScrollbars && height > maxHeight; - + if (desiredHeight != this.desiredHeight || this.$size.height != this.desiredHeight || vScroll != this.$vScroll) { if (vScroll != this.$vScroll) { this.$vScroll = vScroll; this.scrollBarV.setVisible(vScroll); } - + var w = this.container.clientWidth; this.container.style.height = desiredHeight + "px"; this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight); // this.$loop.changes = 0; this.desiredHeight = desiredHeight; - + this._signal("autosize"); } } /** - + * @returns {number} */ $computeLayerConfig() { var session = this.session; var size = this.$size; - + var hideScrollbars = size.height <= 2 * this.lineHeight; var screenLines = this.session.getScreenLength(); var maxHeight = screenLines * this.lineHeight; var longestLine = this.$getLongestLine(); - + var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible || size.scrollerWidth - longestLine - 2 * this.$padding < 0); @@ -1107,19 +1113,19 @@ class VirtualRenderer { this.$autosize(); var minHeight = size.scrollerHeight + this.lineHeight; - + var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd : 0; maxHeight += scrollPastEnd; - + var sm = this.scrollMargin; this.session.setScrollTop(Math.max(-sm.top, Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom))); - this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft, + this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft, longestLine + 2 * this.$padding - size.scrollerWidth + sm.right))); - + var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top); var vScrollChanged = vScrollBefore !== vScroll; @@ -1155,7 +1161,7 @@ class VirtualRenderer { offset = this.scrollTop - firstRowScreen * lineHeight; var changes = 0; - if (this.layerConfig.width != longestLine || hScrollChanged) + if (this.layerConfig.width != longestLine || hScrollChanged) changes = this.CHANGE_H_SCROLL; // Horizontal scrollbar visibility may have changed, which changes // the client height of the scroller @@ -1165,7 +1171,7 @@ class VirtualRenderer { if (vScrollChanged) longestLine = this.$getLongestLine(); } - + this.layerConfig = { width : longestLine, padding : this.$padding, @@ -1191,7 +1197,7 @@ class VirtualRenderer { /** * @returns {boolean | undefined} - + */ $updateLines() { if (!this.$changedLines) return; @@ -1218,15 +1224,15 @@ class VirtualRenderer { } /** - * + * * @returns {number} - + */ $getLongestLine() { var charCount = this.session.getScreenWidth(); if (this.showInvisibles && !this.session.$useWrapMode) charCount += 1; - + if (this.$textLayer && charCount > this.$textLayer.MAX_LINE_LENGTH) charCount = this.$textLayer.MAX_LINE_LENGTH + 30; @@ -1268,7 +1274,7 @@ class VirtualRenderer { } /** - * + * * Redraw breakpoints. * @param {any} [rows] */ @@ -1312,7 +1318,7 @@ class VirtualRenderer { } /** - * + * * @param {Point} anchor * @param {Point} lead * @param {number} [offset] @@ -1324,7 +1330,7 @@ class VirtualRenderer { } /** - * + * * Scrolls the cursor into the first visibile area of the editor * @param {Point} [cursor] * @param {number} [offset] @@ -1426,7 +1432,7 @@ class VirtualRenderer { } /** - * + * * @param {Point} cursor * @param {number} [alignment] * @returns {number} @@ -1444,7 +1450,7 @@ class VirtualRenderer { } /** - * + * * @param {number} fromValue * @param {number} toValue * @returns {*[]} @@ -1470,7 +1476,7 @@ class VirtualRenderer { * @param {Boolean} center If `true`, centers the editor the to indicated line * @param {Boolean} animate If `true` animates scrolling * @param {() => void} [callback] Function to be called after the animation has finished - + **/ scrollToLine(line, center, animate, callback) { var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0}); @@ -1485,20 +1491,20 @@ class VirtualRenderer { } /** - * + * * @param fromValue * @param [callback] - + */ animateScrolling(fromValue, callback) { var toValue = this.scrollTop; if (!this.$animatedScroll) return; var _self = this; - + if (fromValue == toValue) return; - + if (this.$scrollAnimation) { var oldSteps = this.$scrollAnimation.steps; if (oldSteps.length) { @@ -1507,7 +1513,7 @@ class VirtualRenderer { return; } } - + var steps = _self.$calcSteps(fromValue, toValue); this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps}; @@ -1516,7 +1522,7 @@ class VirtualRenderer { _self.session.setScrollTop(steps.shift()); // trick session to think it's already scrolled to not loose toValue _self.session.$scrollTop = toValue; - + function endAnimation() { // @ts-ignore _self.$timer = clearInterval(_self.$timer); @@ -1524,14 +1530,14 @@ class VirtualRenderer { _self.$stopAnimation = false; callback && callback(); } - + this.$timer = setInterval(function() { if (_self.$stopAnimation) { endAnimation(); return; } - if (!_self.session) + if (!_self.session) return clearInterval(_self.$timer); if (steps.length) { _self.session.setScrollTop(steps.shift()); @@ -1579,7 +1585,7 @@ class VirtualRenderer { this.session.setScrollTop(y); this.session.setScrollLeft(x); } - + /** * Scrolls the editor across both x- and y-axes. * @param {Number} deltaX The x value to scroll by @@ -1611,11 +1617,11 @@ class VirtualRenderer { } /** - * + * * @param {number} x * @param {number} y * @returns {import("../ace-internal").Ace.ScreenCoordinates} - + */ pixelToScreenCoordinates(x, y) { var canvasPos; @@ -1627,7 +1633,7 @@ class VirtualRenderer { } else { canvasPos = this.scroller.getBoundingClientRect(); } - + var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding; var offset = offsetX / this.characterWidth; var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight); @@ -1637,11 +1643,11 @@ class VirtualRenderer { } /** - * + * * @param {number} x * @param {number} y * @returns {Point} - + */ screenToTextCoordinates(x, y) { var canvasPos; @@ -1677,7 +1683,7 @@ class VirtualRenderer { var x = this.$padding + (this.session.$bidiHandler.isBidiRow(pos.row, row) ? this.session.$bidiHandler.getPosLeft(pos.column) : Math.round(pos.column * this.characterWidth)); - + var y = pos.row * this.lineHeight; return { @@ -1704,7 +1710,7 @@ class VirtualRenderer { /** * @param {Object} composition - + **/ showComposition(composition) { this.$composition = composition; @@ -1713,7 +1719,7 @@ class VirtualRenderer { } if (composition.useTextareaForIME == undefined) composition.useTextareaForIME = this.$useTextareaForIME; - + if (this.$useTextareaForIME) { dom.addCssClass(this.textarea, "ace_composition"); this.textarea.style.cssText = ""; @@ -1729,7 +1735,7 @@ class VirtualRenderer { * @param {String} text A string of text to use * * Sets the inner text of the current composition to `text`. - + **/ setCompositionText(text) { var cursor = this.session.selection.cursor; @@ -1740,12 +1746,12 @@ class VirtualRenderer { /** * * Hides the current composition. - + **/ hideComposition() { if (!this.$composition) return; - + if (this.$composition.markerId) this.session.removeMarker(this.$composition.markerId); @@ -1766,10 +1772,10 @@ class VirtualRenderer { var insertPosition = position || { row: cursor.row, column: cursor.column }; this.removeGhostText(); - + var textChunks = this.$calculateWrappedTextChunks(text, insertPosition); this.addToken(textChunks[0].text, "ghost_text", insertPosition.row, insertPosition.column); - + this.$ghostText = { text: text, position: { @@ -1777,7 +1783,7 @@ class VirtualRenderer { column: insertPosition. column } }; - + var widgetDiv = dom.createElement("div"); if (textChunks.length > 1) { // If there are tokens to the right of the cursor, hide those. @@ -1787,20 +1793,20 @@ class VirtualRenderer { textChunks.slice(1).forEach(el => { var chunkDiv = dom.createElement("div"); var chunkSpan = dom.createElement("span"); - chunkSpan.className = "ace_ghost_text"; + chunkSpan.className = "ace_ghost_text"; // If the line is wider than the viewport, wrap the line if (el.wrapped) chunkDiv.className = "ghost_text_line_wrapped"; - // If a given line doesn't have text (e.g. it's a line of whitespace), set a space as the + // If a given line doesn't have text (e.g. it's a line of whitespace), set a space as the // textcontent so that browsers render the empty line div. - if (el.text.length === 0) el.text = " "; - + if (el.text.length === 0) el.text = " "; + chunkSpan.appendChild(dom.createTextNode(el.text)); chunkDiv.appendChild(chunkSpan); widgetDiv.appendChild(chunkDiv); - // Overwrite lastLineDiv every iteration so at the end it points to + // Overwrite lastLineDiv every iteration so at the end it points to // the last added element. lastLineDiv = chunkDiv; }); @@ -1812,7 +1818,7 @@ class VirtualRenderer { element.appendChild(dom.createTextNode(token.value)); lastLineDiv.appendChild(element); }); - + this.$ghostTextWidget = { el: widgetDiv, row: insertPosition.row, @@ -1830,7 +1836,7 @@ class VirtualRenderer { // If it fits, no action needed if (fitsY) return; - + // If it can fully fit in the screen, scroll down until it fits on the screen // if it cannot fully fit, scroll so that the row with the cursor // is at the top of the screen. @@ -1838,13 +1844,13 @@ class VirtualRenderer { this.scrollBy(0, (textChunks.length - 1) * this.lineHeight); } else { this.scrollToRow(insertPosition.row); - } + } } - + } /** - * Calculates and organizes text into wrapped chunks. Initially splits the text by newline characters, + * Calculates and organizes text into wrapped chunks. Initially splits the text by newline characters, * then further processes each line based on display tokens and session settings for tab size and wrapping limits. * * @param {string} text @@ -1913,7 +1919,7 @@ class VirtualRenderer { var diff = token.value.length - (l - column); var before = token.value.slice(0, diff); var after = token.value.slice(diff); - + tokens.splice(i, 1, {type: token.type, value: before}, newToken, {type: token.type, value: after}); break; } @@ -1942,10 +1948,10 @@ class VirtualRenderer { continue; } // We call this method after we call addToken, so we are guaranteed a new token starts at the cursor position. - // Once we reached that point in the loop, flip the flag. + // Once we reached that point in the loop, flip the flag. if (l === column) { hasPassedCursor = true; - } + } } this.updateLines(row, row); return hiddenTokens; @@ -1960,7 +1966,7 @@ class VirtualRenderer { * [Sets a new theme for the editor. `theme` should exist, and be a directory path, like `ace/theme/textmate`.]{: #VirtualRenderer.setTheme} * @param {String | Theme} [theme] The path to a theme * @param {() => void} [cb] optional callback - + **/ setTheme(theme, cb) { var _self = this; @@ -1994,11 +2000,11 @@ class VirtualRenderer { if (_self.theme) dom.removeCssClass(_self.container, _self.theme.cssClass); /**@type {any}*/ - var padding = "padding" in module ? module.padding + var padding = "padding" in module ? module.padding : "padding" in (_self.theme || {}) ? 4 : _self.$padding; if (_self.$padding && padding != _self.$padding) _self.setPadding(padding); - + // this is kept only for backwards compatibility _self.$theme = module.cssClass; @@ -2067,14 +2073,14 @@ class VirtualRenderer { setMouseCursor(cursorStyle) { dom.setStyle(this.scroller.style, "cursor", cursorStyle); } - + attachToShadowRoot() { dom.importCssString(editorCss, "ace_editor.css", this.container); } /** * Destroys the text and cursor layers for this renderer. - + **/ destroy() { this.freeze(); @@ -2086,7 +2092,7 @@ class VirtualRenderer { } /** - * + * * @param {boolean} [val] */ $updateCustomScrollbar(val) { @@ -2127,7 +2133,7 @@ class VirtualRenderer { } /** - + */ $addResizeObserver() { if (!window.ResizeObserver || this.$resizeObserver) return; @@ -2214,7 +2220,7 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", { this.$updatePrintMargin(); }, get: function() { - return this.$showPrintMargin && this.$printMarginColumn; + return this.$showPrintMargin && this.$printMarginColumn; } }, showGutter: {