diff --git a/NOTICE.txt b/NOTICE.txt
index 3cee52c089cb4..80d49de19e5db 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -74,37 +74,6 @@ under a "BSD" license.
Distributed under the BSD license:
-Copyright (c) 2010, Ajax.org B.V.
-All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of Ajax.org B.V. nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
----
-This product includes code that is based on Ace editor, which was available
-under a "BSD" license.
-
-Distributed under the BSD license:
-
Copyright (c) 2010, Ajax.org B.V.
All rights reserved.
diff --git a/src/plugins/console/README.md b/src/plugins/console/README.md
index 02da27229286a..35921de334380 100644
--- a/src/plugins/console/README.md
+++ b/src/plugins/console/README.md
@@ -44,7 +44,7 @@ POST /_some_endpoint
```
## Architecture
-Console uses Ace editor that is wrapped with [`CoreEditor`](https://github.com/elastic/kibana/blob/main/src/plugins/console/public/types/core_editor.ts), so that if needed it can easily be replaced with another editor, for example Monaco.
+Console uses Monaco editor that is wrapped with [`kbn-monaco`](https://github.com/elastic/kibana/blob/main/packages/kbn-monaco/index.ts), so that if needed it can easily be replaced with another editor.
The autocomplete logic is located in [`autocomplete`](https://github.com/elastic/kibana/blob/main/src/plugins/console/public/lib/autocomplete) folder. Autocomplete rules are computed by classes in `components` sub-folder.
## Autocomplete definitions
@@ -317,8 +317,4 @@ Another change is replacing jQuery with the core http client to communicate with
### Outstanding issues
#### Autocomplete suggestions for Kibana API endpoints
Console currently supports autocomplete suggestions for Elasticsearch API endpoints. The autocomplete suggestions for Kibana API endpoints are not supported yet.
-Related issue: [#130661](https://github.com/elastic/kibana/issues/130661)
-
-#### Migration to Monaco Editor
-Console plugin is currently using Ace Editor and it is planned to migrate to Monaco Editor in the future.
-Related issue: [#57435](https://github.com/elastic/kibana/issues/57435)
\ No newline at end of file
+Related issue: [#130661](https://github.com/elastic/kibana/issues/130661)
\ No newline at end of file
diff --git a/src/plugins/console/public/application/contexts/editor_context/editor_registry.ts b/src/plugins/console/public/application/contexts/editor_context/editor_registry.ts
index 8197ff0460e86..dc7b58ecbd267 100644
--- a/src/plugins/console/public/application/contexts/editor_context/editor_registry.ts
+++ b/src/plugins/console/public/application/contexts/editor_context/editor_registry.ts
@@ -8,12 +8,11 @@
*/
import { MonacoEditorActionsProvider } from '../../containers/editor/monaco_editor_actions_provider';
-import { SenseEditor } from '../../models/sense_editor';
export class EditorRegistry {
- private inputEditor: SenseEditor | MonacoEditorActionsProvider | undefined;
+ private inputEditor: MonacoEditorActionsProvider | undefined;
- setInputEditor(inputEditor: SenseEditor | MonacoEditorActionsProvider) {
+ setInputEditor(inputEditor: MonacoEditorActionsProvider) {
this.inputEditor = inputEditor;
}
diff --git a/src/plugins/console/public/application/hooks/index.ts b/src/plugins/console/public/application/hooks/index.ts
index b6b7211a940e4..29c554771dad0 100644
--- a/src/plugins/console/public/application/hooks/index.ts
+++ b/src/plugins/console/public/application/hooks/index.ts
@@ -8,7 +8,6 @@
*/
export { useSetInputEditor } from './use_set_input_editor';
-export { useRestoreRequestFromHistory } from './use_restore_request_from_history';
-export { useSendCurrentRequest, sendRequest } from './use_send_current_request';
+export { sendRequest } from './use_send_current_request';
export { useSaveCurrentTextObject } from './use_save_current_text_object';
export { useDataInit } from './use_data_init';
diff --git a/src/plugins/console/public/application/hooks/use_restore_request_from_history/index.ts b/src/plugins/console/public/application/hooks/use_restore_request_from_history/index.ts
deleted file mode 100644
index 47f12868d9bc6..0000000000000
--- a/src/plugins/console/public/application/hooks/use_restore_request_from_history/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-export { useRestoreRequestFromHistory } from './use_restore_request_from_history';
diff --git a/src/plugins/console/public/application/hooks/use_restore_request_from_history/restore_request_from_history.ts b/src/plugins/console/public/application/hooks/use_restore_request_from_history/restore_request_from_history.ts
deleted file mode 100644
index 897e499dc481e..0000000000000
--- a/src/plugins/console/public/application/hooks/use_restore_request_from_history/restore_request_from_history.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import RowParser from '../../../lib/row_parser';
-import { ESRequest } from '../../../types';
-import { SenseEditor } from '../../models/sense_editor';
-import { formatRequestBodyDoc } from '../../../lib/utils';
-
-export function restoreRequestFromHistory(editor: SenseEditor, req: ESRequest) {
- const coreEditor = editor.getCoreEditor();
- let pos = coreEditor.getCurrentPosition();
- let prefix = '';
- let suffix = '\n';
- const parser = new RowParser(coreEditor);
- if (parser.isStartRequestRow(pos.lineNumber)) {
- pos.column = 1;
- suffix += '\n';
- } else if (parser.isEndRequestRow(pos.lineNumber)) {
- const line = coreEditor.getLineValue(pos.lineNumber);
- pos.column = line.length + 1;
- prefix = '\n\n';
- } else if (parser.isInBetweenRequestsRow(pos.lineNumber)) {
- pos.column = 1;
- } else {
- pos = editor.nextRequestEnd(pos);
- prefix = '\n\n';
- }
-
- let s = prefix + req.method + ' ' + req.endpoint;
- if (req.data) {
- const indent = true;
- const formattedData = formatRequestBodyDoc([req.data], indent);
- s += '\n' + formattedData.data;
- }
-
- s += suffix;
-
- coreEditor.insert(pos, s);
- coreEditor.moveCursorToPosition({ lineNumber: pos.lineNumber + prefix.length, column: 1 });
- coreEditor.clearSelection();
- coreEditor.getContainer().focus();
-}
diff --git a/src/plugins/console/public/application/hooks/use_restore_request_from_history/restore_request_from_history_to_monaco.ts b/src/plugins/console/public/application/hooks/use_restore_request_from_history/restore_request_from_history_to_monaco.ts
deleted file mode 100644
index 08c2bc6af86a3..0000000000000
--- a/src/plugins/console/public/application/hooks/use_restore_request_from_history/restore_request_from_history_to_monaco.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { formatRequestBodyDoc } from '../../../lib/utils';
-import { MonacoEditorActionsProvider } from '../../containers/editor/monaco_editor_actions_provider';
-import { ESRequest } from '../../../types';
-
-export async function restoreRequestFromHistoryToMonaco(
- provider: MonacoEditorActionsProvider,
- req: ESRequest
-) {
- let s = req.method + ' ' + req.endpoint;
- if (req.data) {
- const indent = true;
- const formattedData = formatRequestBodyDoc([req.data], indent);
- s += '\n' + formattedData.data;
- }
- await provider.restoreRequestFromHistory(s);
-}
diff --git a/src/plugins/console/public/application/hooks/use_restore_request_from_history/use_restore_request_from_history.ts b/src/plugins/console/public/application/hooks/use_restore_request_from_history/use_restore_request_from_history.ts
deleted file mode 100644
index 5ee0d185923c2..0000000000000
--- a/src/plugins/console/public/application/hooks/use_restore_request_from_history/use_restore_request_from_history.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { useCallback } from 'react';
-import { instance as registry } from '../../contexts/editor_context/editor_registry';
-import { ESRequest } from '../../../types';
-import { restoreRequestFromHistoryToMonaco } from './restore_request_from_history_to_monaco';
-import { MonacoEditorActionsProvider } from '../../containers/editor/monaco_editor_actions_provider';
-
-export const useRestoreRequestFromHistory = () => {
- return useCallback(async (req: ESRequest) => {
- const editor = registry.getInputEditor();
- await restoreRequestFromHistoryToMonaco(editor as MonacoEditorActionsProvider, req);
- }, []);
-};
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request/index.ts b/src/plugins/console/public/application/hooks/use_send_current_request/index.ts
index 753184f67e998..656c0b939cf5b 100644
--- a/src/plugins/console/public/application/hooks/use_send_current_request/index.ts
+++ b/src/plugins/console/public/application/hooks/use_send_current_request/index.ts
@@ -7,5 +7,4 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
-export { useSendCurrentRequest } from './use_send_current_request';
export { sendRequest } from './send_request';
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request/track.ts b/src/plugins/console/public/application/hooks/use_send_current_request/track.ts
deleted file mode 100644
index e663c0b8354c1..0000000000000
--- a/src/plugins/console/public/application/hooks/use_send_current_request/track.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { SenseEditor } from '../../models/sense_editor';
-import { getEndpointFromPosition } from '../../../lib/autocomplete/get_endpoint_from_position';
-import { MetricsTracker } from '../../../types';
-
-export const track = (
- requests: Array<{ method: string }>,
- editor: SenseEditor,
- trackUiMetric: MetricsTracker
-) => {
- const coreEditor = editor.getCoreEditor();
- // `getEndpointFromPosition` gets values from the server-side generated JSON files which
- // are a combination of JS, automatically generated JSON and manual overrides. That means
- // the metrics reported from here will be tied to the definitions in those files.
- // See src/legacy/core_plugins/console/server/api_server/spec
- const endpointDescription = getEndpointFromPosition(
- coreEditor,
- coreEditor.getCurrentPosition(),
- editor.parser
- );
-
- if (requests[0] && endpointDescription) {
- const eventName = `${requests[0].method}_${endpointDescription.id ?? 'unknown'}`;
- trackUiMetric.count(eventName);
- }
-};
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.test.tsx b/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.test.tsx
deleted file mode 100644
index 7f3082d5ef3dc..0000000000000
--- a/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.test.tsx
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-jest.mock('./send_request', () => ({ sendRequest: jest.fn() }));
-jest.mock('../../contexts/editor_context/editor_registry', () => ({
- instance: { getInputEditor: jest.fn() },
-}));
-jest.mock('./track', () => ({ track: jest.fn() }));
-jest.mock('../../contexts/request_context', () => ({ useRequestActionContext: jest.fn() }));
-jest.mock('../../../lib/utils', () => ({ replaceVariables: jest.fn() }));
-
-import React from 'react';
-import { renderHook, act } from '@testing-library/react-hooks';
-
-import { ContextValue, ServicesContextProvider } from '../../contexts';
-import { serviceContextMock } from '../../contexts/services_context.mock';
-import { useRequestActionContext } from '../../contexts/request_context';
-import { instance as editorRegistry } from '../../contexts/editor_context/editor_registry';
-import * as utils from '../../../lib/utils';
-
-import { sendRequest } from './send_request';
-import { useSendCurrentRequest } from './use_send_current_request';
-
-describe('useSendCurrentRequest', () => {
- let mockContextValue: ContextValue;
- let dispatch: (...args: unknown[]) => void;
- const contexts = ({ children }: { children: JSX.Element }) => (
- {children}
- );
-
- beforeEach(() => {
- mockContextValue = serviceContextMock.create();
- dispatch = jest.fn();
- (useRequestActionContext as jest.Mock).mockReturnValue(dispatch);
- (utils.replaceVariables as jest.Mock).mockReturnValue(['test']);
- });
-
- afterEach(() => {
- jest.resetAllMocks();
- });
-
- it('calls send request', async () => {
- // Set up mocks
- (mockContextValue.services.settings.toJSON as jest.Mock).mockReturnValue({});
- // This request should succeed
- (sendRequest as jest.Mock).mockResolvedValue([]);
- (editorRegistry.getInputEditor as jest.Mock).mockImplementation(() => ({
- getRequestsInRange: () => ['test'],
- }));
-
- const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
- await act(() => result.current());
- expect(sendRequest).toHaveBeenCalledWith({
- http: mockContextValue.services.http,
- requests: ['test'],
- });
-
- // Second call should be the request success
- const [, [requestSucceededCall]] = (dispatch as jest.Mock).mock.calls;
- expect(requestSucceededCall).toEqual({ type: 'requestSuccess', payload: { data: [] } });
- });
-
- it('handles known errors', async () => {
- // Set up mocks
- (sendRequest as jest.Mock).mockRejectedValue({ response: 'nada' });
- (editorRegistry.getInputEditor as jest.Mock).mockImplementation(() => ({
- getRequestsInRange: () => ['test'],
- }));
-
- const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
- await act(() => result.current());
- // Second call should be the request failure
- const [, [requestFailedCall]] = (dispatch as jest.Mock).mock.calls;
-
- // The request must have concluded
- expect(requestFailedCall).toEqual({ type: 'requestFail', payload: { response: 'nada' } });
- });
-
- it('handles unknown errors', async () => {
- // Set up mocks
- (sendRequest as jest.Mock).mockRejectedValue(NaN /* unexpected error value */);
- (editorRegistry.getInputEditor as jest.Mock).mockImplementation(() => ({
- getRequestsInRange: () => ['test'],
- }));
-
- const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
- await act(() => result.current());
- // Second call should be the request failure
- const [, [requestFailedCall]] = (dispatch as jest.Mock).mock.calls;
-
- // The request must have concluded
- expect(requestFailedCall).toEqual({ type: 'requestFail', payload: undefined });
- // It also notified the user
- expect(mockContextValue.services.notifications.toasts.addError).toHaveBeenCalledWith(NaN, {
- title: 'Unknown Request Error',
- });
- });
-
- it('notifies the user about save to history errors once only', async () => {
- // Set up mocks
- (sendRequest as jest.Mock).mockReturnValue(
- [{ request: {} }, { request: {} }] /* two responses to save history */
- );
- (mockContextValue.services.settings.toJSON as jest.Mock).mockReturnValue({
- isHistoryEnabled: true,
- });
- (mockContextValue.services.history.addToHistory as jest.Mock).mockImplementation(() => {
- // Mock throwing
- throw new Error('cannot save!');
- });
- (editorRegistry.getInputEditor as jest.Mock).mockImplementation(() => ({
- getRequestsInRange: () => ['test', 'test'],
- }));
-
- const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
- await act(() => result.current());
-
- expect(dispatch).toHaveBeenCalledTimes(2);
-
- expect(mockContextValue.services.history.addToHistory).toHaveBeenCalledTimes(2);
- // It only called notification once
- expect(mockContextValue.services.notifications.toasts.addError).toHaveBeenCalledTimes(1);
- });
-});
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.ts b/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.ts
deleted file mode 100644
index afdd5358432e9..0000000000000
--- a/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { i18n } from '@kbn/i18n';
-import { useCallback } from 'react';
-
-import { toMountPoint } from '../../../shared_imports';
-import { isQuotaExceededError } from '../../../services/history';
-import { instance as registry } from '../../contexts/editor_context/editor_registry';
-import { useRequestActionContext, useServicesContext } from '../../contexts';
-import { StorageQuotaError } from '../../components/storage_quota_error';
-import { sendRequest } from './send_request';
-import { track } from './track';
-import { replaceVariables } from '../../../lib/utils';
-import { StorageKeys } from '../../../services';
-import { DEFAULT_VARIABLES } from '../../../../common/constants';
-import { SenseEditor } from '../../models';
-
-export const useSendCurrentRequest = () => {
- const {
- services: { history, settings, notifications, trackUiMetric, http, autocompleteInfo, storage },
- ...startServices
- } = useServicesContext();
-
- const dispatch = useRequestActionContext();
-
- return useCallback(async () => {
- try {
- const editor = registry.getInputEditor() as SenseEditor;
- const variables = storage.get(StorageKeys.VARIABLES, DEFAULT_VARIABLES);
- let requests = await editor.getRequestsInRange();
- requests = replaceVariables(requests, variables);
- if (!requests.length) {
- notifications.toasts.add(
- i18n.translate('console.notification.error.noRequestSelectedTitle', {
- defaultMessage:
- 'No request selected. Select a request by placing the cursor inside it.',
- })
- );
- return;
- }
-
- dispatch({ type: 'sendRequest', payload: undefined });
-
- // Fire and forget
- setTimeout(() => track(requests, editor as SenseEditor, trackUiMetric), 0);
-
- const results = await sendRequest({ http, requests });
-
- let saveToHistoryError: undefined | Error;
- const { isHistoryEnabled } = settings.toJSON();
-
- if (isHistoryEnabled) {
- results.forEach(({ request: { path, method, data } }) => {
- try {
- history.addToHistory(path, method, data);
- } catch (e) {
- // Grab only the first error
- if (!saveToHistoryError) {
- saveToHistoryError = e;
- }
- }
- });
- }
-
- if (saveToHistoryError) {
- const errorTitle = i18n.translate('console.notification.error.couldNotSaveRequestTitle', {
- defaultMessage: 'Could not save request to Console history.',
- });
- if (isQuotaExceededError(saveToHistoryError)) {
- const toast = notifications.toasts.addWarning({
- title: i18n.translate('console.notification.error.historyQuotaReachedMessage', {
- defaultMessage:
- 'Request history is full. Clear the console history or disable saving new requests.',
- }),
- text: toMountPoint(
- StorageQuotaError({
- onClearHistory: () => {
- history.clearHistory();
- notifications.toasts.remove(toast);
- },
- onDisableSavingToHistory: () => {
- settings.setIsHistoryEnabled(false);
- notifications.toasts.remove(toast);
- },
- }),
- startServices
- ),
- });
- } else {
- // Best effort, but still notify the user.
- notifications.toasts.addError(saveToHistoryError, {
- title: errorTitle,
- });
- }
- }
-
- const { polling } = settings.toJSON();
- if (polling) {
- // If the user has submitted a request against ES, something in the fields, indices, aliases,
- // or templates may have changed, so we'll need to update this data. Assume that if
- // the user disables polling they're trying to optimize performance or otherwise
- // preserve resources, so they won't want this request sent either.
- autocompleteInfo.retrieve(settings, settings.getAutocomplete());
- }
-
- dispatch({
- type: 'requestSuccess',
- payload: {
- data: results,
- },
- });
- } catch (e) {
- if (e?.response) {
- dispatch({
- type: 'requestFail',
- payload: e,
- });
- } else {
- dispatch({
- type: 'requestFail',
- payload: undefined,
- });
- notifications.toasts.addError(e, {
- title: i18n.translate('console.notification.error.unknownErrorTitle', {
- defaultMessage: 'Unknown Request Error',
- }),
- });
- }
- }
- }, [
- storage,
- dispatch,
- http,
- settings,
- notifications.toasts,
- trackUiMetric,
- history,
- autocompleteInfo,
- startServices,
- ]);
-};
diff --git a/src/plugins/console/public/application/hooks/use_set_input_editor.ts b/src/plugins/console/public/application/hooks/use_set_input_editor.ts
index d6029420a1772..148ede97520ea 100644
--- a/src/plugins/console/public/application/hooks/use_set_input_editor.ts
+++ b/src/plugins/console/public/application/hooks/use_set_input_editor.ts
@@ -10,14 +10,13 @@
import { useCallback } from 'react';
import { useEditorActionContext } from '../contexts/editor_context';
import { instance as registry } from '../contexts/editor_context/editor_registry';
-import { SenseEditor } from '../models';
import { MonacoEditorActionsProvider } from '../containers/editor/monaco_editor_actions_provider';
export const useSetInputEditor = () => {
const dispatch = useEditorActionContext();
return useCallback(
- (editor: SenseEditor | MonacoEditorActionsProvider) => {
+ (editor: MonacoEditorActionsProvider) => {
dispatch({ type: 'setInputEditor', payload: editor });
registry.setInputEditor(editor);
},
diff --git a/src/plugins/console/public/application/models/index.ts b/src/plugins/console/public/application/models/index.ts
deleted file mode 100644
index 0d4a8f474daee..0000000000000
--- a/src/plugins/console/public/application/models/index.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-export * from './legacy_core_editor/legacy_core_editor';
-export * from './sense_editor';
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/create.ts b/src/plugins/console/public/application/models/legacy_core_editor/create.ts
deleted file mode 100644
index b2631e8d6712b..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/create.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace from 'brace';
-import { LegacyCoreEditor } from './legacy_core_editor';
-
-export const create = (el: HTMLElement) => {
- const actions = document.querySelector('#ConAppEditorActions');
- if (!actions) {
- throw new Error('Could not find ConAppEditorActions element!');
- }
- const aceEditor = ace.edit(el);
- return new LegacyCoreEditor(aceEditor, actions);
-};
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/create_readonly.ts b/src/plugins/console/public/application/models/legacy_core_editor/create_readonly.ts
deleted file mode 100644
index dc0a95c224395..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/create_readonly.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import _ from 'lodash';
-import ace from 'brace';
-import { Mode } from './mode/output';
-import smartResize from './smart_resize';
-
-export interface CustomAceEditor extends ace.Editor {
- update: (text: string, mode?: string | Mode, cb?: () => void) => void;
- append: (text: string, foldPrevious?: boolean, cb?: () => void) => void;
-}
-
-/**
- * Note: using read-only ace editor leaks the Ace editor API - use this as sparingly as possible or
- * create an interface for it so that we don't rely directly on vendor APIs.
- */
-export function createReadOnlyAceEditor(element: HTMLElement): CustomAceEditor {
- const output: CustomAceEditor = ace.acequire('ace/ace').edit(element);
-
- const outputMode = new Mode();
-
- output.$blockScrolling = Infinity;
- output.resize = smartResize(output);
- output.update = (val, mode, cb) => {
- if (typeof mode === 'function') {
- cb = mode as () => void;
- mode = void 0;
- }
-
- const session = output.getSession();
- const currentMode = val ? mode || outputMode : 'ace/mode/text';
-
- // @ts-ignore
- // ignore ts error here due to type definition mistake in brace for setMode(mode: string): void;
- // this method accepts string or SyntaxMode which is an object. See https://github.com/ajaxorg/ace/blob/13dc911dbc0ea31ca343d5744b3f472767458fc3/ace.d.ts#L467
- session.setMode(currentMode);
- session.setValue(val);
- if (typeof cb === 'function') {
- setTimeout(cb);
- }
- };
-
- output.append = (val: string, foldPrevious?: boolean, cb?: () => void) => {
- if (typeof foldPrevious === 'function') {
- cb = foldPrevious;
- foldPrevious = true;
- }
- if (_.isUndefined(foldPrevious)) {
- foldPrevious = true;
- }
- const session = output.getSession();
- const lastLine = session.getLength();
- if (foldPrevious) {
- output.moveCursorTo(Math.max(0, lastLine - 1), 0);
- }
- session.insert({ row: lastLine, column: 0 }, '\n' + val);
- output.moveCursorTo(lastLine + 1, 0);
- if (typeof cb === 'function') {
- setTimeout(cb);
- }
- };
-
- (function setupSession(session) {
- session.setMode('ace/mode/text');
- (session as unknown as { setFoldStyle: (v: string) => void }).setFoldStyle('markbeginend');
- session.setTabSize(2);
- session.setUseWrapMode(true);
- })(output.getSession());
-
- output.setShowPrintMargin(false);
- output.setReadOnly(true);
-
- return output;
-}
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/index.ts b/src/plugins/console/public/application/models/legacy_core_editor/index.ts
deleted file mode 100644
index e885257520245..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/index.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import 'brace';
-import 'brace/ext/language_tools';
-import 'brace/ext/searchbox';
-import 'brace/mode/json';
-import 'brace/mode/text';
-
-export * from './legacy_core_editor';
-export * from './create_readonly';
-export * from './create';
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/input.test.js b/src/plugins/console/public/application/models/legacy_core_editor/input.test.js
deleted file mode 100644
index e472edc1af125..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/input.test.js
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import './legacy_core_editor.test.mocks';
-import RowParser from '../../../lib/row_parser';
-import { createTokenIterator } from '../../factories';
-import $ from 'jquery';
-import { create } from './create';
-
-describe('Input', () => {
- let coreEditor;
- beforeEach(() => {
- // Set up our document body
- document.body.innerHTML = ``;
-
- coreEditor = create(document.querySelector('#ConAppEditor'));
-
- $(coreEditor.getContainer()).show();
- });
- afterEach(() => {
- $(coreEditor.getContainer()).hide();
- });
-
- describe('.getLineCount', () => {
- it('returns the correct line length', async () => {
- await coreEditor.setValue('1\n2\n3\n4', true);
- expect(coreEditor.getLineCount()).toBe(4);
- });
- });
-
- describe('Tokenization', () => {
- function tokensAsList() {
- const iter = createTokenIterator({
- editor: coreEditor,
- position: { lineNumber: 1, column: 1 },
- });
- const ret = [];
- let t = iter.getCurrentToken();
- const parser = new RowParser(coreEditor);
- if (parser.isEmptyToken(t)) {
- t = parser.nextNonEmptyToken(iter);
- }
- while (t) {
- ret.push({ value: t.value, type: t.type });
- t = parser.nextNonEmptyToken(iter);
- }
-
- return ret;
- }
-
- let testCount = 0;
-
- function tokenTest(tokenList, prefix, data) {
- if (data && typeof data !== 'string') {
- data = JSON.stringify(data, null, 3);
- }
- if (data) {
- if (prefix) {
- data = prefix + '\n' + data;
- }
- } else {
- data = prefix;
- }
-
- test('Token test ' + testCount++ + ' prefix: ' + prefix, async function () {
- await coreEditor.setValue(data, true);
- const tokens = tokensAsList();
- const normTokenList = [];
- for (let i = 0; i < tokenList.length; i++) {
- normTokenList.push({ type: tokenList[i++], value: tokenList[i] });
- }
-
- expect(tokens).toEqual(normTokenList);
- });
- }
-
- tokenTest(['method', 'GET', 'url.part', '_search'], 'GET _search');
-
- tokenTest(['method', 'GET', 'url.slash', '/', 'url.part', '_search'], 'GET /_search');
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.protocol_host',
- 'http://somehost',
- 'url.slash',
- '/',
- 'url.part',
- '_search',
- ],
- 'GET http://somehost/_search'
- );
-
- tokenTest(['method', 'GET', 'url.protocol_host', 'http://somehost'], 'GET http://somehost');
-
- tokenTest(
- ['method', 'GET', 'url.protocol_host', 'http://somehost', 'url.slash', '/'],
- 'GET http://somehost/'
- );
-
- tokenTest(
- ['method', 'GET', 'url.protocol_host', 'http://test:user@somehost', 'url.slash', '/'],
- 'GET http://test:user@somehost/'
- );
-
- tokenTest(
- ['method', 'GET', 'url.part', '_cluster', 'url.slash', '/', 'url.part', 'nodes'],
- 'GET _cluster/nodes'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.slash',
- '/',
- 'url.part',
- '_cluster',
- 'url.slash',
- '/',
- 'url.part',
- 'nodes',
- ],
- 'GET /_cluster/nodes'
- );
-
- tokenTest(
- ['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', '_search'],
- 'GET index/_search'
- );
-
- tokenTest(['method', 'GET', 'url.part', 'index'], 'GET index');
-
- tokenTest(
- ['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', 'type'],
- 'GET index/type'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.slash',
- '/',
- 'url.part',
- 'index',
- 'url.slash',
- '/',
- 'url.part',
- 'type',
- 'url.slash',
- '/',
- ],
- 'GET /index/type/'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.part',
- 'index',
- 'url.slash',
- '/',
- 'url.part',
- 'type',
- 'url.slash',
- '/',
- 'url.part',
- '_search',
- ],
- 'GET index/type/_search'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.part',
- 'index',
- 'url.slash',
- '/',
- 'url.part',
- 'type',
- 'url.slash',
- '/',
- 'url.part',
- '_search',
- 'url.questionmark',
- '?',
- 'url.param',
- 'value',
- 'url.equal',
- '=',
- 'url.value',
- '1',
- ],
- 'GET index/type/_search?value=1'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.part',
- 'index',
- 'url.slash',
- '/',
- 'url.part',
- 'type',
- 'url.slash',
- '/',
- 'url.part',
- '1',
- ],
- 'GET index/type/1'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.slash',
- '/',
- 'url.part',
- 'index1',
- 'url.comma',
- ',',
- 'url.part',
- 'index2',
- 'url.slash',
- '/',
- ],
- 'GET /index1,index2/'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.slash',
- '/',
- 'url.part',
- 'index1',
- 'url.comma',
- ',',
- 'url.part',
- 'index2',
- 'url.slash',
- '/',
- 'url.part',
- '_search',
- ],
- 'GET /index1,index2/_search'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.part',
- 'index1',
- 'url.comma',
- ',',
- 'url.part',
- 'index2',
- 'url.slash',
- '/',
- 'url.part',
- '_search',
- ],
- 'GET index1,index2/_search'
- );
-
- tokenTest(
- [
- 'method',
- 'GET',
- 'url.slash',
- '/',
- 'url.part',
- 'index1',
- 'url.comma',
- ',',
- 'url.part',
- 'index2',
- ],
- 'GET /index1,index2'
- );
-
- tokenTest(
- ['method', 'GET', 'url.part', 'index1', 'url.comma', ',', 'url.part', 'index2'],
- 'GET index1,index2'
- );
-
- tokenTest(
- ['method', 'GET', 'url.slash', '/', 'url.part', 'index1', 'url.comma', ','],
- 'GET /index1,'
- );
-
- tokenTest(
- ['method', 'PUT', 'url.slash', '/', 'url.part', 'index', 'url.slash', '/'],
- 'PUT /index/'
- );
-
- tokenTest(
- ['method', 'GET', 'url.part', 'index', 'url.slash', '/', 'url.part', '_search'],
- 'GET index/_search '
- );
-
- tokenTest(['method', 'PUT', 'url.slash', '/', 'url.part', 'index'], 'PUT /index');
-
- tokenTest(
- [
- 'method',
- 'PUT',
- 'url.slash',
- '/',
- 'url.part',
- 'index1',
- 'url.comma',
- ',',
- 'url.part',
- 'index2',
- 'url.slash',
- '/',
- 'url.part',
- 'type1',
- 'url.comma',
- ',',
- 'url.part',
- 'type2',
- ],
- 'PUT /index1,index2/type1,type2'
- );
-
- tokenTest(
- [
- 'method',
- 'PUT',
- 'url.slash',
- '/',
- 'url.part',
- 'index1',
- 'url.slash',
- '/',
- 'url.part',
- 'type1',
- 'url.comma',
- ',',
- 'url.part',
- 'type2',
- 'url.comma',
- ',',
- ],
- 'PUT /index1/type1,type2,'
- );
-
- tokenTest(
- [
- 'method',
- 'PUT',
- 'url.part',
- 'index1',
- 'url.comma',
- ',',
- 'url.part',
- 'index2',
- 'url.slash',
- '/',
- 'url.part',
- 'type1',
- 'url.comma',
- ',',
- 'url.part',
- 'type2',
- 'url.slash',
- '/',
- 'url.part',
- '1234',
- ],
- 'PUT index1,index2/type1,type2/1234'
- );
-
- tokenTest(
- [
- 'method',
- 'POST',
- 'url.part',
- '_search',
- 'paren.lparen',
- '{',
- 'variable',
- '"q"',
- 'punctuation.colon',
- ':',
- 'paren.lparen',
- '{',
- 'paren.rparen',
- '}',
- 'paren.rparen',
- '}',
- ],
- 'POST _search\n' + '{\n' + ' "q": {}\n' + ' \n' + '}'
- );
-
- tokenTest(
- [
- 'method',
- 'POST',
- 'url.part',
- '_search',
- 'paren.lparen',
- '{',
- 'variable',
- '"q"',
- 'punctuation.colon',
- ':',
- 'paren.lparen',
- '{',
- 'variable',
- '"s"',
- 'punctuation.colon',
- ':',
- 'paren.lparen',
- '{',
- 'paren.rparen',
- '}',
- 'paren.rparen',
- '}',
- 'paren.rparen',
- '}',
- ],
- 'POST _search\n' + '{\n' + ' "q": { "s": {}}\n' + ' \n' + '}'
- );
-
- function statesAsList() {
- const ret = [];
- const maxLine = coreEditor.getLineCount();
- for (let line = 1; line <= maxLine; line++) ret.push(coreEditor.getLineState(line));
- return ret;
- }
-
- function statesTest(statesList, prefix, data) {
- if (data && typeof data !== 'string') {
- data = JSON.stringify(data, null, 3);
- }
- if (data) {
- if (prefix) {
- data = prefix + '\n' + data;
- }
- } else {
- data = prefix;
- }
-
- test('States test ' + testCount++ + ' prefix: ' + prefix, async function () {
- await coreEditor.setValue(data, true);
- const modes = statesAsList();
- expect(modes).toEqual(statesList);
- });
- }
-
- statesTest(
- ['start', 'json', 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "query": { "match_all": {} }\n' + '}'
- );
-
- statesTest(
- ['start', 'json', ['json', 'json'], ['json', 'json'], 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "query": { \n' + ' "match_all": {} \n' + ' }\n' + '}'
- );
-
- statesTest(
- ['start', 'json', 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "script": { "source": "" }\n' + '}'
- );
-
- statesTest(
- ['start', 'json', 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "script": ""\n' + '}'
- );
-
- statesTest(
- ['start', 'json', ['json', 'json'], 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "script": {\n' + ' }\n' + '}'
- );
-
- statesTest(
- [
- 'start',
- 'json',
- ['script-start', 'json', 'json', 'json'],
- ['script-start', 'json', 'json', 'json'],
- ['json', 'json'],
- 'json',
- 'start',
- ],
- 'POST _search\n' +
- '{\n' +
- ' "test": { "script": """\n' +
- ' test script\n' +
- ' """\n' +
- ' }\n' +
- '}'
- );
-
- statesTest(
- ['start', 'json', ['script-start', 'json'], ['script-start', 'json'], 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "script": """\n' + ' test script\n' + ' """,\n' + '}'
- );
-
- statesTest(
- ['start', 'json', 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "script": """test script""",\n' + '}'
- );
-
- statesTest(
- ['start', 'json', ['string_literal', 'json'], ['string_literal', 'json'], 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "something": """\n' + ' test script\n' + ' """,\n' + '}'
- );
-
- statesTest(
- [
- 'start',
- 'json',
- ['string_literal', 'json', 'json', 'json'],
- ['string_literal', 'json', 'json', 'json'],
- ['json', 'json'],
- ['json', 'json'],
- 'json',
- 'start',
- ],
- 'POST _search\n' +
- '{\n' +
- ' "something": { "f" : """\n' +
- ' test script\n' +
- ' """,\n' +
- ' "g": 1\n' +
- ' }\n' +
- '}'
- );
-
- statesTest(
- ['start', 'json', 'json', 'start'],
- 'POST _search\n' + '{\n' + ' "something": """test script""",\n' + '}'
- );
- });
-});
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.test.mocks.ts b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.test.mocks.ts
deleted file mode 100644
index 2ef5551e893d1..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.test.mocks.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-jest.mock('./mode/worker', () => {
- return { workerModule: { id: 'sense_editor/mode/worker', src: '' } };
-});
-
-import '@kbn/web-worker-stub';
-
-// @ts-ignore
-window.URL = {
- createObjectURL: () => {
- return '';
- },
-};
-
-import 'brace';
-import 'brace/ext/language_tools';
-import 'brace/ext/searchbox';
-import 'brace/mode/json';
-import 'brace/mode/text';
-
-document.queryCommandSupported = () => true;
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts
deleted file mode 100644
index edeb64104be7f..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace, { type Annotation } from 'brace';
-import { Editor as IAceEditor, IEditSession as IAceEditSession } from 'brace';
-import $ from 'jquery';
-import {
- CoreEditor,
- Position,
- Range,
- Token,
- TokensProvider,
- EditorEvent,
- AutoCompleterFunction,
-} from '../../../types';
-import { AceTokensProvider } from '../../../lib/ace_token_provider';
-import * as curl from '../sense_editor/curl';
-import smartResize from './smart_resize';
-import * as InputMode from './mode/input';
-
-const _AceRange = ace.acequire('ace/range').Range;
-
-const rangeToAceRange = ({ start, end }: Range) =>
- new _AceRange(start.lineNumber - 1, start.column - 1, end.lineNumber - 1, end.column - 1);
-
-export class LegacyCoreEditor implements CoreEditor {
- private _aceOnPaste: Function;
- $actions: JQuery;
- resize: () => void;
-
- constructor(private readonly editor: IAceEditor, actions: HTMLElement) {
- this.$actions = $(actions);
- this.editor.setShowPrintMargin(false);
-
- const session = this.editor.getSession();
- // @ts-expect-error
- // ignore ts error here due to type definition mistake in brace for setMode(mode: string): void;
- // this method accepts string or SyntaxMode which is an object. See https://github.com/ajaxorg/ace/blob/13dc911dbc0ea31ca343d5744b3f472767458fc3/ace.d.ts#L467
- session.setMode(new InputMode.Mode());
- (session as unknown as { setFoldStyle: (style: string) => void }).setFoldStyle('markbeginend');
- session.setTabSize(2);
- session.setUseWrapMode(true);
-
- this.resize = smartResize(this.editor);
-
- // Intercept ace on paste handler.
- this._aceOnPaste = this.editor.onPaste;
- this.editor.onPaste = this.DO_NOT_USE_onPaste.bind(this);
-
- this.editor.setOptions({
- enableBasicAutocompletion: true,
- });
-
- this.editor.$blockScrolling = Infinity;
- this.hideActionsBar();
- this.editor.focus();
- }
-
- // dirty check for tokenizer state, uses a lot less cycles
- // than listening for tokenizerUpdate
- waitForLatestTokens(): Promise {
- return new Promise((resolve) => {
- const session = this.editor.getSession();
- const checkInterval = 25;
-
- const check = () => {
- // If the bgTokenizer doesn't exist, we can assume that the underlying editor has been
- // torn down, e.g. by closing the History tab, and we don't need to do anything further.
- if (session.bgTokenizer) {
- // Wait until the bgTokenizer is done running before executing the callback.
- if ((session.bgTokenizer as unknown as { running: boolean }).running) {
- setTimeout(check, checkInterval);
- } else {
- resolve();
- }
- }
- };
-
- setTimeout(check, 0);
- });
- }
-
- getLineState(lineNumber: number) {
- const session = this.editor.getSession();
- return session.getState(lineNumber - 1);
- }
-
- getValueInRange(range: Range): string {
- return this.editor.getSession().getTextRange(rangeToAceRange(range));
- }
-
- getTokenProvider(): TokensProvider {
- return new AceTokensProvider(this.editor.getSession());
- }
-
- getValue(): string {
- return this.editor.getValue();
- }
-
- async setValue(text: string, forceRetokenize: boolean): Promise {
- const session = this.editor.getSession();
- session.setValue(text);
- if (forceRetokenize) {
- await this.forceRetokenize();
- }
- }
-
- getLineValue(lineNumber: number): string {
- const session = this.editor.getSession();
- return session.getLine(lineNumber - 1);
- }
-
- getCurrentPosition(): Position {
- const cursorPosition = this.editor.getCursorPosition();
- return {
- lineNumber: cursorPosition.row + 1,
- column: cursorPosition.column + 1,
- };
- }
-
- clearSelection(): void {
- this.editor.clearSelection();
- }
-
- getTokenAt(pos: Position): Token | null {
- const provider = this.getTokenProvider();
- return provider.getTokenAt(pos);
- }
-
- insert(valueOrPos: string | Position, value?: string): void {
- if (typeof valueOrPos === 'string') {
- this.editor.insert(valueOrPos);
- return;
- }
- const document = this.editor.getSession().getDocument();
- document.insert(
- {
- column: valueOrPos.column - 1,
- row: valueOrPos.lineNumber - 1,
- },
- value || ''
- );
- }
-
- moveCursorToPosition(pos: Position): void {
- this.editor.moveCursorToPosition({ row: pos.lineNumber - 1, column: pos.column - 1 });
- }
-
- replace(range: Range, value: string): void {
- const session = this.editor.getSession();
- session.replace(rangeToAceRange(range), value);
- }
-
- getLines(startLine: number, endLine: number): string[] {
- const session = this.editor.getSession();
- return session.getLines(startLine - 1, endLine - 1);
- }
-
- replaceRange(range: Range, value: string) {
- const pos = this.editor.getCursorPosition();
- this.editor.getSession().replace(rangeToAceRange(range), value);
-
- const maxRow = Math.max(range.start.lineNumber - 1 + value.split('\n').length - 1, 1);
- pos.row = Math.min(pos.row, maxRow);
- this.editor.moveCursorToPosition(pos);
- // ACE UPGRADE - check if needed - at the moment the above may trigger a selection.
- this.editor.clearSelection();
- }
-
- getSelectionRange() {
- const result = this.editor.getSelectionRange();
- return {
- start: {
- lineNumber: result.start.row + 1,
- column: result.start.column + 1,
- },
- end: {
- lineNumber: result.end.row + 1,
- column: result.end.column + 1,
- },
- };
- }
-
- getLineCount() {
- // Only use this function to return line count as it uses
- // a cache.
- return this.editor.getSession().getLength();
- }
-
- addMarker(range: Range) {
- return this.editor
- .getSession()
- .addMarker(rangeToAceRange(range), 'ace_snippet-marker', 'fullLine', false);
- }
-
- removeMarker(ref: number) {
- this.editor.getSession().removeMarker(ref);
- }
-
- getWrapLimit(): number {
- return this.editor.getSession().getWrapLimit();
- }
-
- on(event: EditorEvent, listener: () => void) {
- if (event === 'changeCursor') {
- this.editor.getSession().selection.on(event, listener);
- } else if (event === 'changeSelection') {
- this.editor.on(event, listener);
- } else {
- this.editor.getSession().on(event, listener);
- }
- }
-
- off(event: EditorEvent, listener: () => void) {
- if (event === 'changeSelection') {
- this.editor.off(event, listener);
- }
- }
-
- isCompleterActive() {
- return Boolean(
- (this.editor as unknown as { completer: { activated: unknown } }).completer &&
- (this.editor as unknown as { completer: { activated: unknown } }).completer.activated
- );
- }
-
- detachCompleter() {
- // In some situations we need to detach the autocomplete suggestions element manually,
- // such as when navigating away from Console when the suggestions list is open.
- const completer = (this.editor as unknown as { completer: { detach(): void } }).completer;
- return completer?.detach();
- }
-
- private forceRetokenize() {
- const session = this.editor.getSession();
- return new Promise((resolve) => {
- // force update of tokens, but not on this thread to allow for ace rendering.
- setTimeout(function () {
- let i;
- for (i = 0; i < session.getLength(); i++) {
- session.getTokens(i);
- }
- resolve();
- });
- });
- }
-
- // eslint-disable-next-line @typescript-eslint/naming-convention
- private DO_NOT_USE_onPaste(text: string) {
- if (text && curl.detectCURL(text)) {
- const curlInput = curl.parseCURL(text);
- this.editor.insert(curlInput);
- return;
- }
- this._aceOnPaste.call(this.editor, text);
- }
-
- private setActionsBar = (value: number | null, topOrBottom: 'top' | 'bottom' = 'top') => {
- if (value === null) {
- this.$actions.css('visibility', 'hidden');
- } else {
- if (topOrBottom === 'top') {
- this.$actions.css({
- bottom: 'auto',
- top: value,
- visibility: 'visible',
- });
- } else {
- this.$actions.css({
- top: 'auto',
- bottom: value,
- visibility: 'visible',
- });
- }
- }
- };
-
- private hideActionsBar = () => {
- this.setActionsBar(null);
- };
-
- execCommand(cmd: string) {
- this.editor.execCommand(cmd);
- }
-
- getContainer(): HTMLDivElement {
- return this.editor.container as HTMLDivElement;
- }
-
- setStyles(styles: { wrapLines: boolean; fontSize: string }) {
- this.editor.getSession().setUseWrapMode(styles.wrapLines);
- this.editor.container.style.fontSize = styles.fontSize;
- }
-
- registerKeyboardShortcut(opts: { keys: string; fn: () => void; name: string }): void {
- this.editor.commands.addCommand({
- exec: opts.fn,
- name: opts.name,
- bindKey: opts.keys,
- });
- }
-
- unregisterKeyboardShortcut(command: string) {
- // @ts-ignore
- this.editor.commands.removeCommand(command);
- }
-
- legacyUpdateUI(range: Range) {
- if (!this.$actions) {
- return;
- }
- if (range) {
- // elements are positioned relative to the editor's container
- // pageY is relative to page, so subtract the offset
- // from pageY to get the new top value
- const offsetFromPage = $(this.editor.container).offset()!.top;
- const startLine = range.start.lineNumber;
- const startColumn = range.start.column;
- const firstLine = this.getLineValue(startLine);
- const maxLineLength = this.getWrapLimit() - 5;
- const isWrapping = firstLine.length > maxLineLength;
- const totalOffset = offsetFromPage - (window.pageYOffset || 0);
- const getScreenCoords = (line: number) =>
- this.editor.renderer.textToScreenCoordinates(line - 1, startColumn).pageY - totalOffset;
- const topOfReq = getScreenCoords(startLine);
-
- if (topOfReq >= 0) {
- const { bottom: maxBottom } = this.editor.container.getBoundingClientRect();
- if (topOfReq > maxBottom - totalOffset) {
- this.setActionsBar(0, 'bottom');
- return;
- }
- let offset = 0;
- if (isWrapping) {
- // Try get the line height of the text area in pixels.
- const textArea = $(this.editor.container.querySelector('textArea')!);
- const hasRoomOnNextLine = this.getLineValue(startLine).length < maxLineLength;
- if (textArea && hasRoomOnNextLine) {
- // Line height + the number of wraps we have on a line.
- offset += this.getLineValue(startLine).length * textArea.height()!;
- } else {
- if (startLine > 1) {
- this.setActionsBar(getScreenCoords(startLine - 1));
- return;
- }
- this.setActionsBar(getScreenCoords(startLine + 1));
- return;
- }
- }
- this.setActionsBar(topOfReq + offset);
- return;
- }
-
- const bottomOfReq =
- this.editor.renderer.textToScreenCoordinates(range.end.lineNumber, range.end.column).pageY -
- offsetFromPage;
-
- if (bottomOfReq >= 0) {
- this.setActionsBar(0);
- return;
- }
- }
- }
-
- registerAutocompleter(autocompleter: AutoCompleterFunction): void {
- // Hook into Ace
-
- // disable standard context based autocompletion.
- // @ts-ignore
- ace.define(
- 'ace/autocomplete/text_completer',
- ['require', 'exports', 'module'],
- function (
- require: unknown,
- exports: {
- getCompletions: (
- innerEditor: unknown,
- session: unknown,
- pos: unknown,
- prefix: unknown,
- callback: (e: null | Error, values: string[]) => void
- ) => void;
- }
- ) {
- exports.getCompletions = function (innerEditor, session, pos, prefix, callback) {
- callback(null, []);
- };
- }
- );
-
- const langTools = ace.acequire('ace/ext/language_tools');
-
- langTools.setCompleters([
- {
- identifierRegexps: [
- /[a-zA-Z_0-9\.\$\-\u00A2-\uFFFF]/, // adds support for dot character
- ],
- getCompletions: (
- // eslint-disable-next-line @typescript-eslint/naming-convention
- DO_NOT_USE_1: IAceEditor,
- aceEditSession: IAceEditSession,
- pos: { row: number; column: number },
- prefix: string,
- callback: (...args: unknown[]) => void
- ) => {
- const position: Position = {
- lineNumber: pos.row + 1,
- column: pos.column + 1,
- };
-
- const getAnnotationControls = () => {
- let customAnnotation: Annotation;
- return {
- setAnnotation(text: string) {
- const annotations = aceEditSession.getAnnotations();
- customAnnotation = {
- text,
- row: pos.row,
- column: pos.column,
- type: 'warning',
- };
-
- aceEditSession.setAnnotations([...annotations, customAnnotation]);
- },
- removeAnnotation() {
- aceEditSession.setAnnotations(
- aceEditSession.getAnnotations().filter((a: Annotation) => a !== customAnnotation)
- );
- },
- };
- };
-
- autocompleter(position, prefix, callback, getAnnotationControls());
- },
- },
- ]);
- }
-
- destroy() {
- this.editor.destroy();
- }
-
- /**
- * Formats body of the request in the editor by removing the extra whitespaces at the beginning of lines,
- * And adds the correct indentation for each line
- * @param reqRange request range to indent
- */
- autoIndent(reqRange: Range) {
- const session = this.editor.getSession();
- const mode = session.getMode();
- const startRow = reqRange.start.lineNumber;
- const endRow = reqRange.end.lineNumber;
- const tab = session.getTabString();
-
- for (let row = startRow; row <= endRow; row++) {
- let prevLineState = '';
- let prevLineIndent = '';
- if (row > 0) {
- prevLineState = session.getState(row - 1);
- const prevLine = session.getLine(row - 1);
- prevLineIndent = mode.getNextLineIndent(prevLineState, prevLine, tab);
- }
-
- const line = session.getLine(row);
- // @ts-ignore
- // Brace does not expose type definition for mode.$getIndent, though we have access to this method provided by the underlying Ace editor.
- // See https://github.com/ajaxorg/ace/blob/87ce087ed1cf20eeabe56fb0894e048d9bc9c481/lib/ace/mode/text.js#L259
- const currLineIndent = mode.$getIndent(line);
- if (prevLineIndent !== currLineIndent) {
- if (currLineIndent.length > 0) {
- // If current line has indentation, remove it.
- // Next we will add the correct indentation by looking at the previous line
- const range = new _AceRange(row, 0, row, currLineIndent.length);
- session.remove(range);
- }
- if (prevLineIndent.length > 0) {
- // If previous line has indentation, add indentation at the current line
- session.insert({ row, column: 0 }, prevLineIndent);
- }
- }
-
- // Lastly outdent any closing braces
- mode.autoOutdent(prevLineState, session, row);
- }
- }
-
- getAllFoldRanges(): Range[] {
- const session = this.editor.getSession();
- // @ts-ignore
- // Brace does not expose type definition for session.getAllFolds, though we have access to this method provided by the underlying Ace editor.
- // See https://github.com/ajaxorg/ace/blob/13dc911dbc0ea31ca343d5744b3f472767458fc3/ace.d.ts#L82
- return session.getAllFolds().map((fold) => fold.range);
- }
-
- addFoldsAtRanges(foldRanges: Range[]) {
- const session = this.editor.getSession();
- foldRanges.forEach((range) => {
- try {
- session.addFold('...', _AceRange.fromPoints(range.start, range.end));
- } catch (e) {
- // ignore the error if a fold fails
- }
- });
- }
-}
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.ts
deleted file mode 100644
index 450feec6e9c3d..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace from 'brace';
-import { workerModule } from './worker';
-import { ScriptMode } from './script';
-
-const TextMode = ace.acequire('ace/mode/text').Mode;
-
-const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent;
-const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour;
-const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode;
-const WorkerClient = ace.acequire('ace/worker/worker_client').WorkerClient;
-const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer;
-
-import { InputHighlightRules } from './input_highlight_rules';
-
-export class Mode extends TextMode {
- constructor() {
- super();
- this.$tokenizer = new AceTokenizer(new InputHighlightRules().getRules());
- this.$outdent = new MatchingBraceOutdent();
- this.$behaviour = new CstyleBehaviour();
- this.foldingRules = new CStyleFoldMode();
- this.createModeDelegates({
- 'script-': ScriptMode,
- });
- }
-}
-
-(function (this: Mode) {
- this.getCompletions = function () {
- // autocomplete is done by the autocomplete module.
- return [];
- };
-
- this.getNextLineIndent = function (state: string, line: string, tab: string) {
- let indent = this.$getIndent(line);
-
- if (state !== 'string_literal') {
- const match = line.match(/^.*[\{\(\[]\s*$/);
- if (match) {
- indent += tab;
- }
- }
-
- return indent;
- };
-
- this.checkOutdent = function (state: unknown, line: string, input: string) {
- return this.$outdent.checkOutdent(line, input);
- };
-
- this.autoOutdent = function (state: unknown, doc: string, row: string) {
- this.$outdent.autoOutdent(doc, row);
- };
- this.createWorker = function (session: {
- getDocument: () => string;
- setAnnotations: (arg0: unknown) => void;
- }) {
- const worker = new WorkerClient(['ace', 'sense_editor'], workerModule, 'SenseWorker');
- worker.attachToDocument(session.getDocument());
- worker.on('error', function (e: { data: unknown }) {
- session.setAnnotations([e.data]);
- });
-
- worker.on('ok', function (anno: { data: unknown }) {
- session.setAnnotations(anno.data);
- });
-
- return worker;
- };
-}).call(Mode.prototype);
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.ts
deleted file mode 100644
index 8a2f64b3c71f4..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace from 'brace';
-import { addXJsonToRules } from '@kbn/ace';
-
-type Token =
- | string
- | { token?: string; regex?: string; next?: string; push?: boolean; include?: string };
-
-export function addEOL(
- tokens: Token[],
- reg: string | RegExp,
- nextIfEOL: string,
- normalNext?: string
-) {
- if (typeof reg === 'object') {
- reg = reg.source;
- }
- return [
- { token: tokens.concat(['whitespace']), regex: reg + '(\\s*)$', next: nextIfEOL },
- { token: tokens, regex: reg, next: normalNext },
- ];
-}
-
-export const mergeTokens = (...args: any[]) => [].concat.apply([], args);
-
-const TextHighlightRules = ace.acequire('ace/mode/text_highlight_rules').TextHighlightRules;
-// translating this to monaco
-export class InputHighlightRules extends TextHighlightRules {
- constructor() {
- super();
- this.$rules = {
- // TODO
- 'start-sql': [
- { token: 'whitespace', regex: '\\s+' },
- { token: 'paren.lparen', regex: '{', next: 'json-sql', push: true },
- { regex: '', next: 'start' },
- ],
- start: mergeTokens(
- [
- // done
- { token: 'warning', regex: '#!.*$' },
- // done
- { include: 'comments' },
- // done
- { token: 'paren.lparen', regex: '{', next: 'json', push: true },
- ],
- // done
- addEOL(['method'], /([a-zA-Z]+)/, 'start', 'method_sep'),
- [
- // done
- {
- token: 'whitespace',
- regex: '\\s+',
- },
- // done
- {
- token: 'text',
- regex: '.+?',
- },
- ]
- ),
- method_sep: mergeTokens(
- // done
- addEOL(
- ['whitespace', 'url.protocol_host', 'url.slash'],
- /(\s+)(https?:\/\/[^?\/,]+)(\/)/,
- 'start',
- 'url'
- ),
- // done
- addEOL(['whitespace', 'variable.template'], /(\s+)(\${\w+})/, 'start', 'url'),
- // done
- addEOL(['whitespace', 'url.protocol_host'], /(\s+)(https?:\/\/[^?\/,]+)/, 'start', 'url'),
- // done
- addEOL(['whitespace', 'url.slash'], /(\s+)(\/)/, 'start', 'url'),
- // done
- addEOL(['whitespace'], /(\s+)/, 'start', 'url')
- ),
- url: mergeTokens(
- // done
- addEOL(['variable.template'], /(\${\w+})/, 'start'),
- // TODO
- addEOL(['url.part'], /(_sql)/, 'start-sql', 'url-sql'),
- // done
- addEOL(['url.part'], /([^?\/,\s]+)/, 'start'),
- // done
- addEOL(['url.comma'], /(,)/, 'start'),
- // done
- addEOL(['url.slash'], /(\/)/, 'start'),
- // done
- addEOL(['url.questionmark'], /(\?)/, 'start', 'urlParams'),
- // done
- addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start')
- ),
- urlParams: mergeTokens(
- // done
- addEOL(['url.param', 'url.equal', 'variable.template'], /([^&=]+)(=)(\${\w+})/, 'start'),
- // done
- addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start'),
- // done
- addEOL(['url.param'], /([^&=]+)/, 'start'),
- // done
- addEOL(['url.amp'], /(&)/, 'start'),
- // done
- addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start')
- ),
- // TODO
- 'url-sql': mergeTokens(
- addEOL(['url.part'], /([^?\/,\s]+)/, 'start-sql'),
- addEOL(['url.comma'], /(,)/, 'start-sql'),
- addEOL(['url.slash'], /(\/)/, 'start-sql'),
- addEOL(['url.questionmark'], /(\?)/, 'start-sql', 'urlParams-sql')
- ),
- // TODO
- 'urlParams-sql': mergeTokens(
- addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start-sql'),
- addEOL(['url.param'], /([^&=]+)/, 'start-sql'),
- addEOL(['url.amp'], /(&)/, 'start-sql')
- ),
- /**
- * Each key in this.$rules considered to be a state in state machine. Regular expressions define the tokens for the current state, as well as the transitions into another state.
- * See for more details https://cloud9-sdk.readme.io/docs/highlighting-rules#section-defining-states
- * *
- * Define a state for comments, these comment rules then can be included in other states. E.g. in 'start' and 'json' states by including { include: 'comments' }
- * This will avoid duplicating the same rules in other states
- */
- comments: [
- {
- // Capture a line comment, indicated by #
- // done
- token: ['comment.punctuation', 'comment.line'],
- regex: /(#)(.*$)/,
- },
- {
- // Begin capturing a block comment, indicated by /*
- // done
- token: 'comment.punctuation',
- regex: /\/\*/,
- push: [
- {
- // Finish capturing a block comment, indicated by */
- // done
- token: 'comment.punctuation',
- regex: /\*\//,
- next: 'pop',
- },
- {
- // done
- defaultToken: 'comment.block',
- },
- ],
- },
- {
- // Capture a line comment, indicated by //
- // done
- token: ['comment.punctuation', 'comment.line'],
- regex: /(\/\/)(.*$)/,
- },
- ],
- };
-
- addXJsonToRules(this, 'json');
- // Add comment rules to json rule set
- this.$rules.json.unshift({ include: 'comments' });
-
- this.$rules.json.unshift({ token: 'variable.template', regex: /("\${\w+}")/ });
-
- if (this instanceof InputHighlightRules) {
- this.normalizeRules();
- }
- }
-}
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/output.ts
deleted file mode 100644
index df7f3c37d55ec..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace from 'brace';
-
-import { OutputJsonHighlightRules } from './output_highlight_rules';
-
-const JSONMode = ace.acequire('ace/mode/json').Mode;
-const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent;
-const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour;
-const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode;
-ace.acequire('ace/worker/worker_client');
-const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer;
-
-export class Mode extends JSONMode {
- constructor() {
- super();
- this.$tokenizer = new AceTokenizer(new OutputJsonHighlightRules().getRules());
- this.$outdent = new MatchingBraceOutdent();
- this.$behaviour = new CstyleBehaviour();
- this.foldingRules = new CStyleFoldMode();
- }
-}
-
-(function (this: Mode) {
- this.createWorker = function () {
- return null;
- };
-
- this.$id = 'sense/mode/input';
-}).call(Mode.prototype);
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.test.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.test.ts
deleted file mode 100644
index a18841aa4dc17..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.test.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { mapStatusCodeToBadge } from './output_highlight_rules';
-
-describe('mapStatusCodeToBadge', () => {
- const testCases = [
- {
- description: 'treats 100 as as default',
- value: '# PUT test-index 100 Continue',
- badge: 'badge.badge--default',
- },
- {
- description: 'treats 200 as success',
- value: '# PUT test-index 200 OK',
- badge: 'badge.badge--success',
- },
- {
- description: 'treats 301 as primary',
- value: '# PUT test-index 301 Moved Permanently',
- badge: 'badge.badge--primary',
- },
- {
- description: 'treats 400 as warning',
- value: '# PUT test-index 404 Not Found',
- badge: 'badge.badge--warning',
- },
- {
- description: 'treats 502 as danger',
- value: '# PUT test-index 502 Bad Gateway',
- badge: 'badge.badge--danger',
- },
- {
- description: 'treats unexpected numbers as danger',
- value: '# PUT test-index 666 Demonic Invasion',
- badge: 'badge.badge--danger',
- },
- {
- description: 'treats no numbers as undefined',
- value: '# PUT test-index',
- badge: undefined,
- },
- ];
-
- testCases.forEach(({ description, value, badge }) => {
- test(description, () => {
- expect(mapStatusCodeToBadge(value)).toBe(badge);
- });
- });
-});
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.ts
deleted file mode 100644
index 765ba3e263f22..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace from 'brace';
-import 'brace/mode/json';
-import { addXJsonToRules } from '@kbn/ace';
-
-const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules').JsonHighlightRules;
-
-export const mapStatusCodeToBadge = (value?: string) => {
- const regExpMatchArray = value?.match(/\d+/);
- if (regExpMatchArray) {
- const status = parseInt(regExpMatchArray[0], 10);
- if (status <= 199) {
- return 'badge.badge--default';
- }
- if (status <= 299) {
- return 'badge.badge--success';
- }
- if (status <= 399) {
- return 'badge.badge--primary';
- }
- if (status <= 499) {
- return 'badge.badge--warning';
- }
- return 'badge.badge--danger';
- }
-};
-
-export class OutputJsonHighlightRules extends JsonHighlightRules {
- constructor() {
- super();
- this.$rules = {};
- addXJsonToRules(this, 'start');
- this.$rules.start.unshift(
- {
- token: 'warning',
- regex: '#!.*$',
- },
- {
- token: 'comment',
- // match a comment starting with a hash at the start of the line
- // ignore status codes and status texts at the end of the line (e.g. # GET _search/foo 200, # GET _search/foo 200 OK)
- regex: /#(.*?)(?=[1-5][0-9][0-9]\s(?:[\sA-Za-z]+)|(?:[1-5][0-9][0-9])|$)/,
- },
- {
- token: mapStatusCodeToBadge,
- // match status codes and status texts at the end of the line (e.g. # GET _search/foo 200, # GET _search/foo 200 OK)
- // this rule allows us to highlight them with the corresponding badge color (e.g. 200 OK -> badge.badge--success)
- regex: /([1-5][0-9][0-9]\s?[\sA-Za-z]+$)/,
- }
- );
-
- if (this instanceof OutputJsonHighlightRules) {
- this.normalizeRules();
- }
- }
-}
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.ts
deleted file mode 100644
index f50b6d3abe8ab..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace from 'brace';
-import { ScriptHighlightRules } from '@kbn/ace';
-
-const TextMode = ace.acequire('ace/mode/text').Mode;
-const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent;
-const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour;
-const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode;
-ace.acequire('ace/tokenizer');
-
-export class ScriptMode extends TextMode {
- constructor() {
- super();
- this.$outdent = new MatchingBraceOutdent();
- this.$behaviour = new CstyleBehaviour();
- this.foldingRules = new CStyleFoldMode();
- }
-}
-
-(function (this: ScriptMode) {
- this.HighlightRules = ScriptHighlightRules;
-
- this.getNextLineIndent = function (state: unknown, line: string, tab: string) {
- let indent = this.$getIndent(line);
- const match = line.match(/^.*[\{\[]\s*$/);
- if (match) {
- indent += tab;
- }
-
- return indent;
- };
-
- this.checkOutdent = function (state: unknown, line: string, input: string) {
- return this.$outdent.checkOutdent(line, input);
- };
-
- this.autoOutdent = function (state: unknown, doc: string, row: string) {
- this.$outdent.autoOutdent(doc, row);
- };
-}).call(ScriptMode.prototype);
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts
deleted file mode 100644
index 8067bec3556ae..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-export declare const workerModule: { id: string; src: string };
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.js
deleted file mode 100644
index 23f636b79e1a6..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import src from '!!raw-loader!./worker';
-
-export const workerModule = {
- id: 'sense_editor/mode/worker',
- src,
-};
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/worker.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/worker.js
deleted file mode 100644
index 65567f377cc52..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/worker.js
+++ /dev/null
@@ -1,2392 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-/* @notice
- *
- * This product includes code that is based on Ace editor, which was available
- * under a "BSD" license.
- *
- * Distributed under the BSD license:
- *
- * Copyright (c) 2010, Ajax.org B.V.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Ajax.org B.V. nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* eslint-disable prettier/prettier,prefer-const,eqeqeq,import/no-commonjs,no-undef,no-sequences,
- block-scoped-var,no-use-before-define,no-var,one-var,guard-for-in,new-cap,no-nested-ternary,no-redeclare,
- no-unused-vars,no-extend-native,no-empty,camelcase,no-proto,@kbn/imports/no_unresolvable_imports */
-/*
- This file is loaded up as a blob by Brace to hand to Ace to load as Jsonp
- (hence the redefining of everything). It is based on the javascript
- mode from the brace distro.
-*/
-function init(window) {
- function resolveModuleId(id, paths) {
- for (let testPath = id, tail = ''; testPath;) {
- let alias = paths[testPath];
- if ('string' === typeof alias) return alias + tail;
- if (alias)
- {return (alias.location.replace(/\/*$/, '/') + (tail || alias.main || alias.name));}
- if (alias === !1) return '';
- let i = testPath.lastIndexOf('/');
- if (-1 === i) break;
- (tail = testPath.substr(i) + tail), (testPath = testPath.slice(0, i));
- }
- return id;
- }
- if (
- !(
- (void 0 !== window.window && window.document) ||
- (window.acequire && window.define)
- )
- ) {
- window.console ||
- ((window.console = function () {
- let msgs = Array.prototype.slice.call(arguments, 0);
- postMessage({ type: 'log', data: msgs });
- }),
- (window.console.error = window.console.warn = window.console.log = window.console.trace =
- window.console)),
- (window.window = window),
- (window.ace = window),
- (window.onerror = function (message, file, line, col, err) {
- postMessage({
- type: 'error',
- data: {
- message: message,
- data: err.data,
- file: file,
- line: line,
- col: col,
- stack: err.stack,
- },
- });
- }),
- (window.normalizeModule = function (parentId, moduleName) {
- if (-1 !== moduleName.indexOf('!')) {
- let chunks = moduleName.split('!');
- return (
- window.normalizeModule(parentId, chunks[0]) +
- '!' +
- window.normalizeModule(parentId, chunks[1])
- );
- }
- if ('.' == moduleName.charAt(0)) {
- let base = parentId
- .split('/')
- .slice(0, -1)
- .join('/');
- for (
- moduleName = (base ? base + '/' : '') + moduleName;
- -1 !== moduleName.indexOf('.') && previous != moduleName;
-
- ) {
- var previous = moduleName;
- moduleName = moduleName
- .replace(/^\.\//, '')
- .replace(/\/\.\//, '/')
- .replace(/[^\/]+\/\.\.\//, '');
- }
- }
- return moduleName;
- }),
- (window.acequire = function acequire(parentId, id) {
- if ((id || ((id = parentId), (parentId = null)), !id.charAt))
- {throw Error(
- 'worker.js acequire() accepts only (parentId, id) as arguments'
- );}
- id = window.normalizeModule(parentId, id);
- let module = window.acequire.modules[id];
- if (module)
- {return (
- module.initialized ||
- ((module.initialized = !0),
- (module.exports = module.factory().exports)),
- module.exports
- );}
- if (!window.acequire.tlns) return console.log('unable to load ' + id);
- let path = resolveModuleId(id, window.acequire.tlns);
- return (
- '.js' != path.slice(-3) && (path += '.js'),
- (window.acequire.id = id),
- (window.acequire.modules[id] = {}),
- importScripts(path),
- window.acequire(parentId, id)
- );
- }),
- (window.acequire.modules = {}),
- (window.acequire.tlns = {}),
- (window.define = function (id, deps, factory) {
- if (
- (2 == arguments.length
- ? ((factory = deps),
- 'string' !== typeof id && ((deps = id), (id = window.acequire.id)))
- : 1 == arguments.length &&
- ((factory = id), (deps = []), (id = window.acequire.id)),
- 'function' !== typeof factory)
- )
- {return (
- (window.acequire.modules[id] = {
- exports: factory,
- initialized: !0,
- }),
- void 0
- );}
- deps.length || (deps = ['require', 'exports', 'module']);
- let req = function (childId) {
- return window.acequire(id, childId);
- };
- window.acequire.modules[id] = {
- exports: {},
- factory: function () {
- let module = this,
- returnExports = factory.apply(
- this,
- deps.map(function (dep) {
- switch (dep) {
- case 'require':
- return req;
- case 'exports':
- return module.exports;
- case 'module':
- return module;
- default:
- return req(dep);
- }
- })
- );
- return returnExports && (module.exports = returnExports), module;
- },
- };
- }),
- (window.define.amd = {}),
- (acequire.tlns = {}),
- (window.initBaseUrls = function (topLevelNamespaces) {
- for (let i in topLevelNamespaces)
- {acequire.tlns[i] = topLevelNamespaces[i];}
- }),
- (window.initSender = function () {
- let EventEmitter = window.acequire('ace/lib/event_emitter')
- .EventEmitter,
- oop = window.acequire('ace/lib/oop'),
- Sender = function () {};
- return (
- function () {
- oop.implement(this, EventEmitter),
- (this.callback = function (data, callbackId) {
- postMessage({ type: 'call', id: callbackId, data: data });
- }),
- (this.emit = function (name, data) {
- postMessage({ type: 'event', name: name, data: data });
- });
- }.call(Sender.prototype),
- new Sender()
- );
- });
- let main = (window.main = null),
- sender = (window.sender = null);
- window.onmessage = function (e) {
- let msg = e.data;
- if (msg.event && sender) sender._signal(msg.event, msg.data);
- else if (msg.command)
- {if (main[msg.command]) main[msg.command].apply(main, msg.args);
- else {
- if (!window[msg.command])
- throw Error('Unknown command:' + msg.command);
- window[msg.command].apply(window, msg.args);
- }}
- else if (msg.init) {
- window.initBaseUrls(msg.tlns),
- acequire('ace/lib/es5-shim'),
- (sender = window.sender = window.initSender());
- let clazz = acequire(msg.module)[msg.classname];
- main = window.main = new clazz(sender);
- }
- };
- }
-}
-init(this);
-ace.define('ace/lib/oop', ['require', 'exports', 'module'], function (
- acequire,
- exports
-) {
- (exports.inherits = function (ctor, superCtor) {
- (ctor.super_ = superCtor),
- (ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: !1,
- writable: !0,
- configurable: !0,
- },
- }));
- }),
- (exports.mixin = function (obj, mixin) {
- for (let key in mixin) obj[key] = mixin[key];
- return obj;
- }),
- (exports.implement = function (proto, mixin) {
- exports.mixin(proto, mixin);
- });
-}),
-ace.define('ace/range', ['require', 'exports', 'module'], function (
- acequire,
- exports
-) {
- let comparePoints = function (p1, p2) {
- return p1.row - p2.row || p1.column - p2.column;
- },
- Range = function (startRow, startColumn, endRow, endColumn) {
- (this.start = { row: startRow, column: startColumn }),
- (this.end = { row: endRow, column: endColumn });
- };
- (function () {
- (this.isEqual = function (range) {
- return (
- this.start.row === range.start.row &&
- this.end.row === range.end.row &&
- this.start.column === range.start.column &&
- this.end.column === range.end.column
- );
- }),
- (this.toString = function () {
- return (
- 'Range: [' +
- this.start.row +
- '/' +
- this.start.column +
- '] -> [' +
- this.end.row +
- '/' +
- this.end.column +
- ']'
- );
- }),
- (this.contains = function (row, column) {
- return 0 == this.compare(row, column);
- }),
- (this.compareRange = function (range) {
- let cmp,
- end = range.end,
- start = range.start;
- return (
- (cmp = this.compare(end.row, end.column)),
- 1 == cmp
- ? ((cmp = this.compare(start.row, start.column)),
- 1 == cmp ? 2 : 0 == cmp ? 1 : 0)
- : -1 == cmp
- ? -2
- : ((cmp = this.compare(start.row, start.column)),
- -1 == cmp ? -1 : 1 == cmp ? 42 : 0)
- );
- }),
- (this.comparePoint = function (p) {
- return this.compare(p.row, p.column);
- }),
- (this.containsRange = function (range) {
- return (
- 0 == this.comparePoint(range.start) &&
- 0 == this.comparePoint(range.end)
- );
- }),
- (this.intersects = function (range) {
- let cmp = this.compareRange(range);
- return -1 == cmp || 0 == cmp || 1 == cmp;
- }),
- (this.isEnd = function (row, column) {
- return this.end.row == row && this.end.column == column;
- }),
- (this.isStart = function (row, column) {
- return this.start.row == row && this.start.column == column;
- }),
- (this.setStart = function (row, column) {
- 'object' === typeof row
- ? ((this.start.column = row.column), (this.start.row = row.row))
- : ((this.start.row = row), (this.start.column = column));
- }),
- (this.setEnd = function (row, column) {
- 'object' === typeof row
- ? ((this.end.column = row.column), (this.end.row = row.row))
- : ((this.end.row = row), (this.end.column = column));
- }),
- (this.inside = function (row, column) {
- return 0 == this.compare(row, column)
- ? this.isEnd(row, column) || this.isStart(row, column)
- ? !1
- : !0
- : !1;
- }),
- (this.insideStart = function (row, column) {
- return 0 == this.compare(row, column)
- ? this.isEnd(row, column)
- ? !1
- : !0
- : !1;
- }),
- (this.insideEnd = function (row, column) {
- return 0 == this.compare(row, column)
- ? this.isStart(row, column)
- ? !1
- : !0
- : !1;
- }),
- (this.compare = function (row, column) {
- return this.isMultiLine() || row !== this.start.row
- ? this.start.row > row
- ? -1
- : row > this.end.row
- ? 1
- : this.start.row === row
- ? column >= this.start.column
- ? 0
- : -1
- : this.end.row === row
- ? this.end.column >= column
- ? 0
- : 1
- : 0
- : this.start.column > column
- ? -1
- : column > this.end.column
- ? 1
- : 0;
- }),
- (this.compareStart = function (row, column) {
- return this.start.row == row && this.start.column == column
- ? -1
- : this.compare(row, column);
- }),
- (this.compareEnd = function (row, column) {
- return this.end.row == row && this.end.column == column
- ? 1
- : this.compare(row, column);
- }),
- (this.compareInside = function (row, column) {
- return this.end.row == row && this.end.column == column
- ? 1
- : this.start.row == row && this.start.column == column
- ? -1
- : this.compare(row, column);
- }),
- (this.clipRows = function (firstRow, lastRow) {
- if (this.end.row > lastRow) var end = { row: lastRow + 1, column: 0 };
- else if (firstRow > this.end.row)
- {var end = { row: firstRow, column: 0 };}
- if (this.start.row > lastRow)
- {var start = { row: lastRow + 1, column: 0 };}
- else if (firstRow > this.start.row)
- {var start = { row: firstRow, column: 0 };}
- return Range.fromPoints(start || this.start, end || this.end);
- }),
- (this.extend = function (row, column) {
- let cmp = this.compare(row, column);
- if (0 == cmp) return this;
- if (-1 == cmp) var start = { row: row, column: column };
- else var end = { row: row, column: column };
- return Range.fromPoints(start || this.start, end || this.end);
- }),
- (this.isEmpty = function () {
- return (
- this.start.row === this.end.row &&
- this.start.column === this.end.column
- );
- }),
- (this.isMultiLine = function () {
- return this.start.row !== this.end.row;
- }),
- (this.clone = function () {
- return Range.fromPoints(this.start, this.end);
- }),
- (this.collapseRows = function () {
- return 0 == this.end.column
- ? new Range(
- this.start.row,
- 0,
- Math.max(this.start.row, this.end.row - 1),
- 0
- )
- : new Range(this.start.row, 0, this.end.row, 0);
- }),
- (this.toScreenRange = function (session) {
- let screenPosStart = session.documentToScreenPosition(this.start),
- screenPosEnd = session.documentToScreenPosition(this.end);
- return new Range(
- screenPosStart.row,
- screenPosStart.column,
- screenPosEnd.row,
- screenPosEnd.column
- );
- }),
- (this.moveBy = function (row, column) {
- (this.start.row += row),
- (this.start.column += column),
- (this.end.row += row),
- (this.end.column += column);
- });
- }.call(Range.prototype),
- (Range.fromPoints = function (start, end) {
- return new Range(start.row, start.column, end.row, end.column);
- }),
- (Range.comparePoints = comparePoints),
- (Range.comparePoints = function (p1, p2) {
- return p1.row - p2.row || p1.column - p2.column;
- }),
- (exports.Range = Range));
-}),
-ace.define('ace/apply_delta', ['require', 'exports', 'module'], function (
- acequire,
- exports
-) {
- exports.applyDelta = function (docLines, delta) {
- let row = delta.start.row,
- startColumn = delta.start.column,
- line = docLines[row] || '';
- switch (delta.action) {
- case 'insert':
- var lines = delta.lines;
- if (1 === lines.length)
- {docLines[row] =
- line.substring(0, startColumn) +
- delta.lines[0] +
- line.substring(startColumn);}
- else {
- let args = [row, 1].concat(delta.lines);
- docLines.splice.apply(docLines, args),
- (docLines[row] = line.substring(0, startColumn) + docLines[row]),
- (docLines[row + delta.lines.length - 1] += line.substring(
- startColumn
- ));
- }
- break;
- case 'remove':
- var endColumn = delta.end.column,
- endRow = delta.end.row;
- row === endRow
- ? (docLines[row] =
- line.substring(0, startColumn) + line.substring(endColumn))
- : docLines.splice(
- row,
- endRow - row + 1,
- line.substring(0, startColumn) +
- docLines[endRow].substring(endColumn)
- );
- }
- };
-}),
-ace.define(
- 'ace/lib/event_emitter',
- ['require', 'exports', 'module'],
- function (acequire, exports) {
- let EventEmitter = {},
- stopPropagation = function () {
- this.propagationStopped = !0;
- },
- preventDefault = function () {
- this.defaultPrevented = !0;
- };
- (EventEmitter._emit = EventEmitter._dispatchEvent = function (
- eventName,
- e
- ) {
- this._eventRegistry || (this._eventRegistry = {}),
- this._defaultHandlers || (this._defaultHandlers = {});
- let listeners = this._eventRegistry[eventName] || [],
- defaultHandler = this._defaultHandlers[eventName];
- if (listeners.length || defaultHandler) {
- ('object' === typeof e && e) || (e = {}),
- e.type || (e.type = eventName),
- e.stopPropagation || (e.stopPropagation = stopPropagation),
- e.preventDefault || (e.preventDefault = preventDefault),
- (listeners = listeners.slice());
- for (
- let i = 0;
- listeners.length > i &&
- (listeners[i](e, this), !e.propagationStopped);
- i++
- );
- return defaultHandler && !e.defaultPrevented
- ? defaultHandler(e, this)
- : void 0;
- }
- }),
- (EventEmitter._signal = function (eventName, e) {
- let listeners = (this._eventRegistry || {})[eventName];
- if (listeners) {
- listeners = listeners.slice();
- for (let i = 0; listeners.length > i; i++) listeners[i](e, this);
- }
- }),
- (EventEmitter.once = function (eventName, callback) {
- let _self = this;
- callback &&
- this.addEventListener(eventName, function newCallback() {
- _self.removeEventListener(eventName, newCallback),
- callback.apply(null, arguments);
- });
- }),
- (EventEmitter.setDefaultHandler = function (eventName, callback) {
- let handlers = this._defaultHandlers;
- if (
- (handlers ||
- (handlers = this._defaultHandlers = { _disabled_: {} }),
- handlers[eventName])
- ) {
- let old = handlers[eventName],
- disabled = handlers._disabled_[eventName];
- disabled || (handlers._disabled_[eventName] = disabled = []),
- disabled.push(old);
- let i = disabled.indexOf(callback);
- -1 != i && disabled.splice(i, 1);
- }
- handlers[eventName] = callback;
- }),
- (EventEmitter.removeDefaultHandler = function (eventName, callback) {
- let handlers = this._defaultHandlers;
- if (handlers) {
- let disabled = handlers._disabled_[eventName];
- if (handlers[eventName] == callback)
- {handlers[eventName],
- disabled && this.setDefaultHandler(eventName, disabled.pop());}
- else if (disabled) {
- let i = disabled.indexOf(callback);
- -1 != i && disabled.splice(i, 1);
- }
- }
- }),
- (EventEmitter.on = EventEmitter.addEventListener = function (
- eventName,
- callback,
- capturing
- ) {
- this._eventRegistry = this._eventRegistry || {};
- let listeners = this._eventRegistry[eventName];
- return (
- listeners || (listeners = this._eventRegistry[eventName] = []),
- -1 == listeners.indexOf(callback) &&
- listeners[capturing ? 'unshift' : 'push'](callback),
- callback
- );
- }),
- (EventEmitter.off = EventEmitter.removeListener = EventEmitter.removeEventListener = function (
- eventName,
- callback
- ) {
- this._eventRegistry = this._eventRegistry || {};
- let listeners = this._eventRegistry[eventName];
- if (listeners) {
- let index = listeners.indexOf(callback);
- -1 !== index && listeners.splice(index, 1);
- }
- }),
- (EventEmitter.removeAllListeners = function (eventName) {
- this._eventRegistry && (this._eventRegistry[eventName] = []);
- }),
- (exports.EventEmitter = EventEmitter);
- }
-),
-ace.define(
- 'ace/anchor',
- ['require', 'exports', 'module', 'ace/lib/oop', 'ace/lib/event_emitter'],
- function (acequire, exports) {
- let oop = acequire('./lib/oop'),
- EventEmitter = acequire('./lib/event_emitter').EventEmitter,
- Anchor = (exports.Anchor = function (doc, row, column) {
- (this.$onChange = this.onChange.bind(this)),
- this.attach(doc),
- column === void 0
- ? this.setPosition(row.row, row.column)
- : this.setPosition(row, column);
- });
- (function () {
- function $pointsInOrder(point1, point2, equalPointsInOrder) {
- let bColIsAfter = equalPointsInOrder
- ? point1.column <= point2.column
- : point1.column < point2.column;
- return (
- point1.row < point2.row || (point1.row == point2.row && bColIsAfter)
- );
- }
- function $getTransformedPoint(delta, point, moveIfEqual) {
- let deltaIsInsert = 'insert' == delta.action,
- deltaRowShift =
- (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row),
- deltaColShift =
- (deltaIsInsert ? 1 : -1) *
- (delta.end.column - delta.start.column),
- deltaStart = delta.start,
- deltaEnd = deltaIsInsert ? deltaStart : delta.end;
- return $pointsInOrder(point, deltaStart, moveIfEqual)
- ? { row: point.row, column: point.column }
- : $pointsInOrder(deltaEnd, point, !moveIfEqual)
- ? {
- row: point.row + deltaRowShift,
- column:
- point.column +
- (point.row == deltaEnd.row ? deltaColShift : 0),
- }
- : { row: deltaStart.row, column: deltaStart.column };
- }
- oop.implement(this, EventEmitter),
- (this.getPosition = function () {
- return this.$clipPositionToDocument(this.row, this.column);
- }),
- (this.getDocument = function () {
- return this.document;
- }),
- (this.$insertRight = !1),
- (this.onChange = function (delta) {
- if (
- !(
- (delta.start.row == delta.end.row &&
- delta.start.row != this.row) ||
- delta.start.row > this.row
- )
- ) {
- let point = $getTransformedPoint(
- delta,
- { row: this.row, column: this.column },
- this.$insertRight
- );
- this.setPosition(point.row, point.column, !0);
- }
- }),
- (this.setPosition = function (row, column, noClip) {
- let pos;
- if (
- ((pos = noClip
- ? { row: row, column: column }
- : this.$clipPositionToDocument(row, column)),
- this.row != pos.row || this.column != pos.column)
- ) {
- let old = { row: this.row, column: this.column };
- (this.row = pos.row),
- (this.column = pos.column),
- this._signal('change', { old: old, value: pos });
- }
- }),
- (this.detach = function () {
- this.document.removeEventListener('change', this.$onChange);
- }),
- (this.attach = function (doc) {
- (this.document = doc || this.document),
- this.document.on('change', this.$onChange);
- }),
- (this.$clipPositionToDocument = function (row, column) {
- let pos = {};
- return (
- row >= this.document.getLength()
- ? ((pos.row = Math.max(0, this.document.getLength() - 1)),
- (pos.column = this.document.getLine(pos.row).length))
- : 0 > row
- ? ((pos.row = 0), (pos.column = 0))
- : ((pos.row = row),
- (pos.column = Math.min(
- this.document.getLine(pos.row).length,
- Math.max(0, column)
- ))),
- 0 > column && (pos.column = 0),
- pos
- );
- });
- }.call(Anchor.prototype));
- }
-),
-ace.define(
- 'ace/document',
- [
- 'require',
- 'exports',
- 'module',
- 'ace/lib/oop',
- 'ace/apply_delta',
- 'ace/lib/event_emitter',
- 'ace/range',
- 'ace/anchor',
- ],
- function (acequire, exports) {
- let oop = acequire('./lib/oop'),
- applyDelta = acequire('./apply_delta').applyDelta,
- EventEmitter = acequire('./lib/event_emitter').EventEmitter,
- Range = acequire('./range').Range,
- Anchor = acequire('./anchor').Anchor,
- Document = function (textOrLines) {
- (this.$lines = ['']),
- 0 === textOrLines.length
- ? (this.$lines = [''])
- : Array.isArray(textOrLines)
- ? this.insertMergedLines({ row: 0, column: 0 }, textOrLines)
- : this.insert({ row: 0, column: 0 }, textOrLines);
- };
- (function () {
- oop.implement(this, EventEmitter),
- (this.setValue = function (text) {
- let len = this.getLength() - 1;
- this.remove(new Range(0, 0, len, this.getLine(len).length)),
- this.insert({ row: 0, column: 0 }, text);
- }),
- (this.getValue = function () {
- return this.getAllLines().join(this.getNewLineCharacter());
- }),
- (this.createAnchor = function (row, column) {
- return new Anchor(this, row, column);
- }),
- (this.$split =
- 0 === 'aaa'.split(/a/).length
- ? function (text) {
- return text.replace(/\r\n|\r/g, '\n').split('\n');
- }
- : function (text) {
- return text.split(/\r\n|\r|\n/);
- }),
- (this.$detectNewLine = function (text) {
- let match = text.match(/^.*?(\r\n|\r|\n)/m);
- (this.$autoNewLine = match ? match[1] : '\n'),
- this._signal('changeNewLineMode');
- }),
- (this.getNewLineCharacter = function () {
- switch (this.$newLineMode) {
- case 'windows':
- return '\r\n';
- case 'unix':
- return '\n';
- default:
- return this.$autoNewLine || '\n';
- }
- }),
- (this.$autoNewLine = ''),
- (this.$newLineMode = 'auto'),
- (this.setNewLineMode = function (newLineMode) {
- this.$newLineMode !== newLineMode &&
- ((this.$newLineMode = newLineMode),
- this._signal('changeNewLineMode'));
- }),
- (this.getNewLineMode = function () {
- return this.$newLineMode;
- }),
- (this.isNewLine = function (text) {
- return '\r\n' == text || '\r' == text || '\n' == text;
- }),
- (this.getLine = function (row) {
- return this.$lines[row] || '';
- }),
- (this.getLines = function (firstRow, lastRow) {
- return this.$lines.slice(firstRow, lastRow + 1);
- }),
- (this.getAllLines = function () {
- return this.getLines(0, this.getLength());
- }),
- (this.getLength = function () {
- return this.$lines.length;
- }),
- (this.getTextRange = function (range) {
- return this.getLinesForRange(range).join(
- this.getNewLineCharacter()
- );
- }),
- (this.getLinesForRange = function (range) {
- let lines;
- if (range.start.row === range.end.row)
- {lines = [
- this.getLine(range.start.row).substring(
- range.start.column,
- range.end.column
- ),
- ];}
- else {
- (lines = this.getLines(range.start.row, range.end.row)),
- (lines[0] = (lines[0] || '').substring(range.start.column));
- let l = lines.length - 1;
- range.end.row - range.start.row == l &&
- (lines[l] = lines[l].substring(0, range.end.column));
- }
- return lines;
- }),
- (this.insertLines = function (row, lines) {
- return (
- console.warn(
- 'Use of document.insertLines is deprecated. Use the insertFullLines method instead.'
- ),
- this.insertFullLines(row, lines)
- );
- }),
- (this.removeLines = function (firstRow, lastRow) {
- return (
- console.warn(
- 'Use of document.removeLines is deprecated. Use the removeFullLines method instead.'
- ),
- this.removeFullLines(firstRow, lastRow)
- );
- }),
- (this.insertNewLine = function (position) {
- return (
- console.warn(
- 'Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'
- ),
- this.insertMergedLines(position, ['', ''])
- );
- }),
- (this.insert = function (position, text) {
- return (
- 1 >= this.getLength() && this.$detectNewLine(text),
- this.insertMergedLines(position, this.$split(text))
- );
- }),
- (this.insertInLine = function (position, text) {
- let start = this.clippedPos(position.row, position.column),
- end = this.pos(position.row, position.column + text.length);
- return (
- this.applyDelta(
- { start: start, end: end, action: 'insert', lines: [text] },
- !0
- ),
- this.clonePos(end)
- );
- }),
- (this.clippedPos = function (row, column) {
- let length = this.getLength();
- void 0 === row
- ? (row = length)
- : 0 > row
- ? (row = 0)
- : row >= length && ((row = length - 1), (column = void 0));
- let line = this.getLine(row);
- return (
- void 0 == column && (column = line.length),
- (column = Math.min(Math.max(column, 0), line.length)),
- { row: row, column: column }
- );
- }),
- (this.clonePos = function (pos) {
- return { row: pos.row, column: pos.column };
- }),
- (this.pos = function (row, column) {
- return { row: row, column: column };
- }),
- (this.$clipPosition = function (position) {
- let length = this.getLength();
- return (
- position.row >= length
- ? ((position.row = Math.max(0, length - 1)),
- (position.column = this.getLine(length - 1).length))
- : ((position.row = Math.max(0, position.row)),
- (position.column = Math.min(
- Math.max(position.column, 0),
- this.getLine(position.row).length
- ))),
- position
- );
- }),
- (this.insertFullLines = function (row, lines) {
- row = Math.min(Math.max(row, 0), this.getLength());
- let column = 0;
- this.getLength() > row
- ? ((lines = lines.concat([''])), (column = 0))
- : ((lines = [''].concat(lines)),
- row--,
- (column = this.$lines[row].length)),
- this.insertMergedLines({ row: row, column: column }, lines);
- }),
- (this.insertMergedLines = function (position, lines) {
- let start = this.clippedPos(position.row, position.column),
- end = {
- row: start.row + lines.length - 1,
- column:
- (1 == lines.length ? start.column : 0) +
- lines[lines.length - 1].length,
- };
- return (
- this.applyDelta({
- start: start,
- end: end,
- action: 'insert',
- lines: lines,
- }),
- this.clonePos(end)
- );
- }),
- (this.remove = function (range) {
- let start = this.clippedPos(range.start.row, range.start.column),
- end = this.clippedPos(range.end.row, range.end.column);
- return (
- this.applyDelta({
- start: start,
- end: end,
- action: 'remove',
- lines: this.getLinesForRange({ start: start, end: end }),
- }),
- this.clonePos(start)
- );
- }),
- (this.removeInLine = function (row, startColumn, endColumn) {
- let start = this.clippedPos(row, startColumn),
- end = this.clippedPos(row, endColumn);
- return (
- this.applyDelta(
- {
- start: start,
- end: end,
- action: 'remove',
- lines: this.getLinesForRange({ start: start, end: end }),
- },
- !0
- ),
- this.clonePos(start)
- );
- }),
- (this.removeFullLines = function (firstRow, lastRow) {
- (firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1)),
- (lastRow = Math.min(Math.max(0, lastRow), this.getLength() - 1));
- let deleteFirstNewLine =
- lastRow == this.getLength() - 1 && firstRow > 0,
- deleteLastNewLine = this.getLength() - 1 > lastRow,
- startRow = deleteFirstNewLine ? firstRow - 1 : firstRow,
- startCol = deleteFirstNewLine ? this.getLine(startRow).length : 0,
- endRow = deleteLastNewLine ? lastRow + 1 : lastRow,
- endCol = deleteLastNewLine ? 0 : this.getLine(endRow).length,
- range = new Range(startRow, startCol, endRow, endCol),
- deletedLines = this.$lines.slice(firstRow, lastRow + 1);
- return (
- this.applyDelta({
- start: range.start,
- end: range.end,
- action: 'remove',
- lines: this.getLinesForRange(range),
- }),
- deletedLines
- );
- }),
- (this.removeNewLine = function (row) {
- this.getLength() - 1 > row &&
- row >= 0 &&
- this.applyDelta({
- start: this.pos(row, this.getLine(row).length),
- end: this.pos(row + 1, 0),
- action: 'remove',
- lines: ['', ''],
- });
- }),
- (this.replace = function (range, text) {
- if (
- (range instanceof Range ||
- (range = Range.fromPoints(range.start, range.end)),
- 0 === text.length && range.isEmpty())
- )
- {return range.start;}
- if (text == this.getTextRange(range)) return range.end;
- this.remove(range);
- let end;
- return (end = text ? this.insert(range.start, text) : range.start);
- }),
- (this.applyDeltas = function (deltas) {
- for (let i = 0; deltas.length > i; i++) this.applyDelta(deltas[i]);
- }),
- (this.revertDeltas = function (deltas) {
- for (let i = deltas.length - 1; i >= 0; i--)
- {this.revertDelta(deltas[i]);}
- }),
- (this.applyDelta = function (delta, doNotValidate) {
- let isInsert = 'insert' == delta.action;
- (isInsert
- ? 1 >= delta.lines.length && !delta.lines[0]
- : !Range.comparePoints(delta.start, delta.end)) ||
- (isInsert &&
- delta.lines.length > 2e4 &&
- this.$splitAndapplyLargeDelta(delta, 2e4),
- applyDelta(this.$lines, delta, doNotValidate),
- this._signal('change', delta));
- }),
- (this.$splitAndapplyLargeDelta = function (delta, MAX) {
- for (
- let lines = delta.lines,
- l = lines.length,
- row = delta.start.row,
- column = delta.start.column,
- from = 0,
- to = 0;
- ;
-
- ) {
- (from = to), (to += MAX - 1);
- let chunk = lines.slice(from, to);
- if (to > l) {
- (delta.lines = chunk),
- (delta.start.row = row + from),
- (delta.start.column = column);
- break;
- }
- chunk.push(''),
- this.applyDelta(
- {
- start: this.pos(row + from, column),
- end: this.pos(row + to, (column = 0)),
- action: delta.action,
- lines: chunk,
- },
- !0
- );
- }
- }),
- (this.revertDelta = function (delta) {
- this.applyDelta({
- start: this.clonePos(delta.start),
- end: this.clonePos(delta.end),
- action: 'insert' == delta.action ? 'remove' : 'insert',
- lines: delta.lines.slice(),
- });
- }),
- (this.indexToPosition = function (index, startRow) {
- for (
- var lines = this.$lines || this.getAllLines(),
- newlineLength = this.getNewLineCharacter().length,
- i = startRow || 0,
- l = lines.length;
- l > i;
- i++
- )
- {if (((index -= lines[i].length + newlineLength), 0 > index))
- return {
- row: i,
- column: index + lines[i].length + newlineLength,
- };}
- return { row: l - 1, column: lines[l - 1].length };
- }),
- (this.positionToIndex = function (pos, startRow) {
- for (
- var lines = this.$lines || this.getAllLines(),
- newlineLength = this.getNewLineCharacter().length,
- index = 0,
- row = Math.min(pos.row, lines.length),
- i = startRow || 0;
- row > i;
- ++i
- )
- {index += lines[i].length + newlineLength;}
- return index + pos.column;
- });
- }.call(Document.prototype),
- (exports.Document = Document));
- }
-),
-ace.define('ace/lib/lang', ['require', 'exports', 'module'], function (
- acequire,
- exports
-) {
- (exports.last = function (a) {
- return a[a.length - 1];
- }),
- (exports.stringReverse = function (string) {
- return string
- .split('')
- .reverse()
- .join('');
- }),
- (exports.stringRepeat = function (string, count) {
- for (var result = ''; count > 0;)
- {1 & count && (result += string), (count >>= 1) && (string += string);}
- return result;
- });
- let trimBeginRegexp = /^\s\s*/,
- trimEndRegexp = /\s\s*$/;
- (exports.stringTrimLeft = function (string) {
- return string.replace(trimBeginRegexp, '');
- }),
- (exports.stringTrimRight = function (string) {
- return string.replace(trimEndRegexp, '');
- }),
- (exports.copyObject = function (obj) {
- let copy = {};
- for (let key in obj) copy[key] = obj[key];
- return copy;
- }),
- (exports.copyArray = function (array) {
- for (var copy = [], i = 0, l = array.length; l > i; i++)
- {copy[i] =
- array[i] && 'object' == typeof array[i]
- ? this.copyObject(array[i])
- : array[i];}
- return copy;
- }),
- (exports.deepCopy = function deepCopy(obj) {
- if ('object' !== typeof obj || !obj) return obj;
- let copy;
- if (Array.isArray(obj)) {
- copy = [];
- for (var key = 0; obj.length > key; key++)
- {copy[key] = deepCopy(obj[key]);}
- return copy;
- }
- if ('[object Object]' !== Object.prototype.toString.call(obj))
- {return obj;}
- copy = {};
- for (var key in obj) copy[key] = deepCopy(obj[key]);
- return copy;
- }),
- (exports.arrayToMap = function (arr) {
- for (var map = {}, i = 0; arr.length > i; i++) map[arr[i]] = 1;
- return map;
- }),
- (exports.createMap = function (props) {
- let map = Object.create(null);
- for (let i in props) map[i] = props[i];
- return map;
- }),
- (exports.arrayRemove = function (array, value) {
- for (let i = 0; array.length >= i; i++)
- {value === array[i] && array.splice(i, 1);}
- }),
- (exports.escapeRegExp = function (str) {
- return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
- }),
- (exports.escapeHTML = function (str) {
- return str
- .replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(/'/g, ''')
- .replace(/ i; i += 2) {
- if (Array.isArray(data[i + 1]))
- var d = {
- action: 'insert',
- start: data[i],
- lines: data[i + 1],
- };
- else
- var d = {
- action: 'remove',
- start: data[i],
- end: data[i + 1],
- };
- doc.applyDelta(d, !0);
- }}
- return _self.$timeout
- ? deferredUpdate.schedule(_self.$timeout)
- : (_self.onUpdate(), void 0);
- });
- });
- (function () {
- (this.$timeout = 500),
- (this.setTimeout = function (timeout) {
- this.$timeout = timeout;
- }),
- (this.setValue = function (value) {
- this.doc.setValue(value),
- this.deferredUpdate.schedule(this.$timeout);
- }),
- (this.getValue = function (callbackId) {
- this.sender.callback(this.doc.getValue(), callbackId);
- }),
- (this.onUpdate = function () {}),
- (this.isPending = function () {
- return this.deferredUpdate.isPending();
- });
- }.call(Mirror.prototype));
- }
-),
-ace.define('ace/lib/es5-shim', ['require', 'exports', 'module'], function () {
- function Empty() {}
- function doesDefinePropertyWork(object) {
- try {
- return (
- Object.defineProperty(object, 'sentinel', {}), 'sentinel' in object
- );
- } catch (exception) {}
- }
- function toInteger(n) {
- return (
- (n = +n),
- n !== n
- ? (n = 0)
- : 0 !== n &&
- n !== 1 / 0 &&
- n !== -(1 / 0) &&
- (n = (n > 0 || -1) * Math.floor(Math.abs(n))),
- n
- );
- }
- Function.prototype.bind ||
- (Function.prototype.bind = function (that) {
- let target = this;
- if ('function' !== typeof target)
- {throw new TypeError(
- 'Function.prototype.bind called on incompatible ' + target
- );}
- var args = slice.call(arguments, 1),
- bound = function () {
- if (this instanceof bound) {
- let result = target.apply(
- this,
- args.concat(slice.call(arguments))
- );
- return Object(result) === result ? result : this;
- }
- return target.apply(that, args.concat(slice.call(arguments)));
- };
- return (
- target.prototype &&
- ((Empty.prototype = target.prototype),
- (bound.prototype = new Empty()),
- (Empty.prototype = null)),
- bound
- );
- });
- var defineGetter,
- defineSetter,
- lookupGetter,
- lookupSetter,
- supportsAccessors,
- call = Function.prototype.call,
- prototypeOfArray = Array.prototype,
- prototypeOfObject = Object.prototype,
- slice = prototypeOfArray.slice,
- _toString = call.bind(prototypeOfObject.toString),
- owns = call.bind(prototypeOfObject.hasOwnProperty);
- if (
- ((supportsAccessors = owns(prototypeOfObject, '__defineGetter__')) &&
- ((defineGetter = call.bind(prototypeOfObject.__defineGetter__)),
- (defineSetter = call.bind(prototypeOfObject.__defineSetter__)),
- (lookupGetter = call.bind(prototypeOfObject.__lookupGetter__)),
- (lookupSetter = call.bind(prototypeOfObject.__lookupSetter__))),
- 2 != [1, 2].splice(0).length)
- )
- {if (
- (function() {
- function makeArray(l) {
- var a = Array(l + 2);
- return (a[0] = a[1] = 0), a;
- }
- var lengthBefore,
- array = [];
- return (
- array.splice.apply(array, makeArray(20)),
- array.splice.apply(array, makeArray(26)),
- (lengthBefore = array.length),
- array.splice(5, 0, 'XXX'),
- lengthBefore + 1 == array.length,
- lengthBefore + 1 == array.length ? !0 : void 0
- );
- })()
- ) {
- var array_splice = Array.prototype.splice;
- Array.prototype.splice = function(start, deleteCount) {
- return arguments.length
- ? array_splice.apply(
- this,
- [
- void 0 === start ? 0 : start,
- void 0 === deleteCount ? this.length - start : deleteCount,
- ].concat(slice.call(arguments, 2))
- )
- : [];
- };
- } else
- Array.prototype.splice = function(pos, removeCount) {
- var length = this.length;
- pos > 0
- ? pos > length && (pos = length)
- : void 0 == pos
- ? (pos = 0)
- : 0 > pos && (pos = Math.max(length + pos, 0)),
- length > pos + removeCount || (removeCount = length - pos);
- var removed = this.slice(pos, pos + removeCount),
- insert = slice.call(arguments, 2),
- add = insert.length;
- if (pos === length) add && this.push.apply(this, insert);
- else {
- var remove = Math.min(removeCount, length - pos),
- tailOldPos = pos + remove,
- tailNewPos = tailOldPos + add - remove,
- tailCount = length - tailOldPos,
- lengthAfterRemove = length - remove;
- if (tailOldPos > tailNewPos)
- for (var i = 0; tailCount > i; ++i)
- this[tailNewPos + i] = this[tailOldPos + i];
- else if (tailNewPos > tailOldPos)
- for (i = tailCount; i--; )
- this[tailNewPos + i] = this[tailOldPos + i];
- if (add && pos === lengthAfterRemove)
- (this.length = lengthAfterRemove), this.push.apply(this, insert);
- else
- for (this.length = lengthAfterRemove + add, i = 0; add > i; ++i)
- this[pos + i] = insert[i];
- }
- return removed;
- };}
- Array.isArray ||
- (Array.isArray = function (obj) {
- return '[object Array]' == _toString(obj);
- });
- let boxedString = Object('a'),
- splitString = 'a' != boxedString[0] || !(0 in boxedString);
- if (
- (Array.prototype.forEach ||
- (Array.prototype.forEach = function (fun) {
- let object = toObject(this),
- self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : object,
- thisp = arguments[1],
- i = -1,
- length = self.length >>> 0;
- if ('[object Function]' != _toString(fun)) throw new TypeError();
- for (; length > ++i;)
- {i in self && fun.call(thisp, self[i], i, object);}
- }),
- Array.prototype.map ||
- (Array.prototype.map = function (fun) {
- let object = toObject(this),
- self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : object,
- length = self.length >>> 0,
- result = Array(length),
- thisp = arguments[1];
- if ('[object Function]' != _toString(fun))
- {throw new TypeError(fun + ' is not a function');}
- for (let i = 0; length > i; i++)
- {i in self && (result[i] = fun.call(thisp, self[i], i, object));}
- return result;
- }),
- Array.prototype.filter ||
- (Array.prototype.filter = function (fun) {
- let value,
- object = toObject(this),
- self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : object,
- length = self.length >>> 0,
- result = [],
- thisp = arguments[1];
- if ('[object Function]' != _toString(fun))
- {throw new TypeError(fun + ' is not a function');}
- for (let i = 0; length > i; i++)
- {i in self &&
- ((value = self[i]),
- fun.call(thisp, value, i, object) && result.push(value));}
- return result;
- }),
- Array.prototype.every ||
- (Array.prototype.every = function (fun) {
- let object = toObject(this),
- self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : object,
- length = self.length >>> 0,
- thisp = arguments[1];
- if ('[object Function]' != _toString(fun))
- {throw new TypeError(fun + ' is not a function');}
- for (let i = 0; length > i; i++)
- {if (i in self && !fun.call(thisp, self[i], i, object)) return !1;}
- return !0;
- }),
- Array.prototype.some ||
- (Array.prototype.some = function (fun) {
- let object = toObject(this),
- self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : object,
- length = self.length >>> 0,
- thisp = arguments[1];
- if ('[object Function]' != _toString(fun))
- {throw new TypeError(fun + ' is not a function');}
- for (let i = 0; length > i; i++)
- {if (i in self && fun.call(thisp, self[i], i, object)) return !0;}
- return !1;
- }),
- Array.prototype.reduce ||
- (Array.prototype.reduce = function (fun) {
- let object = toObject(this),
- self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : object,
- length = self.length >>> 0;
- if ('[object Function]' != _toString(fun))
- {throw new TypeError(fun + ' is not a function');}
- if (!length && 1 == arguments.length)
- {throw new TypeError('reduce of empty array with no initial value');}
- let result,
- i = 0;
- if (arguments.length >= 2) result = arguments[1];
- else
- {for (;;) {
- if (i in self) {
- result = self[i++];
- break;
- }
- if (++i >= length)
- throw new TypeError(
- 'reduce of empty array with no initial value'
- );
- }}
- for (; length > i; i++)
- {i in self &&
- (result = fun.call(void 0, result, self[i], i, object));}
- return result;
- }),
- Array.prototype.reduceRight ||
- (Array.prototype.reduceRight = function (fun) {
- let object = toObject(this),
- self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : object,
- length = self.length >>> 0;
- if ('[object Function]' != _toString(fun))
- {throw new TypeError(fun + ' is not a function');}
- if (!length && 1 == arguments.length)
- {throw new TypeError(
- 'reduceRight of empty array with no initial value'
- );}
- let result,
- i = length - 1;
- if (arguments.length >= 2) result = arguments[1];
- else
- {for (;;) {
- if (i in self) {
- result = self[i--];
- break;
- }
- if (0 > --i)
- throw new TypeError(
- 'reduceRight of empty array with no initial value'
- );
- }}
- do
- {i in this &&
- (result = fun.call(void 0, result, self[i], i, object));}
- while (i--);
- return result;
- }),
- (Array.prototype.indexOf && -1 == [0, 1].indexOf(1, 2)) ||
- (Array.prototype.indexOf = function (sought) {
- let self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : toObject(this),
- length = self.length >>> 0;
- if (!length) return -1;
- let i = 0;
- for (
- arguments.length > 1 && (i = toInteger(arguments[1])),
- i = i >= 0 ? i : Math.max(0, length + i);
- length > i;
- i++
- )
- {if (i in self && self[i] === sought) return i;}
- return -1;
- }),
- (Array.prototype.lastIndexOf && -1 == [0, 1].lastIndexOf(0, -3)) ||
- (Array.prototype.lastIndexOf = function (sought) {
- let self =
- splitString && '[object String]' == _toString(this)
- ? this.split('')
- : toObject(this),
- length = self.length >>> 0;
- if (!length) return -1;
- let i = length - 1;
- for (
- arguments.length > 1 && (i = Math.min(i, toInteger(arguments[1]))),
- i = i >= 0 ? i : length - Math.abs(i);
- i >= 0;
- i--
- )
- {if (i in self && sought === self[i]) return i;}
- return -1;
- }),
- Object.getPrototypeOf ||
- (Object.getPrototypeOf = function (object) {
- return (
- object.__proto__ ||
- (object.constructor
- ? object.constructor.prototype
- : prototypeOfObject)
- );
- }),
- !Object.getOwnPropertyDescriptor)
- ) {
- let ERR_NON_OBJECT =
- 'Object.getOwnPropertyDescriptor called on a non-object: ';
- Object.getOwnPropertyDescriptor = function (object, property) {
- if (
- ('object' !== typeof object && 'function' !== typeof object) ||
- null === object
- )
- {throw new TypeError(ERR_NON_OBJECT + object);}
- if (owns(object, property)) {
- var descriptor, getter, setter;
- if (
- ((descriptor = { enumerable: !0, configurable: !0 }),
- supportsAccessors)
- ) {
- let prototype = object.__proto__;
- object.__proto__ = prototypeOfObject;
- var getter = lookupGetter(object, property),
- setter = lookupSetter(object, property);
- if (((object.__proto__ = prototype), getter || setter))
- {return (
- getter && (descriptor.get = getter),
- setter && (descriptor.set = setter),
- descriptor
- );}
- }
- return (descriptor.value = object[property]), descriptor;
- }
- };
- }
- if (
- (Object.getOwnPropertyNames ||
- (Object.getOwnPropertyNames = function (object) {
- return Object.keys(object);
- }),
- !Object.create)
- ) {
- let createEmpty;
- (createEmpty =
- null === Object.prototype.__proto__
- ? function () {
- return { __proto__: null };
- }
- : function () {
- let empty = {};
- for (let i in empty) empty[i] = null;
- return (
- (empty.constructor = empty.hasOwnProperty = empty.propertyIsEnumerable = empty.isPrototypeOf = empty.toLocaleString = empty.toString = empty.valueOf = empty.__proto__ = null),
- empty
- );
- }),
- (Object.create = function (prototype, properties) {
- let object;
- if (null === prototype) object = createEmpty();
- else {
- if ('object' !== typeof prototype)
- {throw new TypeError(
- 'typeof prototype[' + typeof prototype + "] != 'object'"
- );}
- let Type = function () {};
- (Type.prototype = prototype),
- (object = new Type()),
- (object.__proto__ = prototype);
- }
- return (
- void 0 !== properties &&
- Object.defineProperties(object, properties),
- object
- );
- });
- }
- if (Object.defineProperty) {
- let definePropertyWorksOnObject = doesDefinePropertyWork({}),
- definePropertyWorksOnDom =
- 'undefined' === typeof document ||
- doesDefinePropertyWork(document.createElement('div'));
- if (!definePropertyWorksOnObject || !definePropertyWorksOnDom)
- {var definePropertyFallback = Object.defineProperty;}
- }
- if (!Object.defineProperty || definePropertyFallback) {
- let ERR_NON_OBJECT_DESCRIPTOR =
- 'Property description must be an object: ',
- ERR_NON_OBJECT_TARGET = 'Object.defineProperty called on non-object: ',
- ERR_ACCESSORS_NOT_SUPPORTED =
- 'getters & setters can not be defined on this javascript engine';
- Object.defineProperty = function (object, property, descriptor) {
- if (
- ('object' !== typeof object && 'function' !== typeof object) ||
- null === object
- )
- {throw new TypeError(ERR_NON_OBJECT_TARGET + object);}
- if (
- ('object' !== typeof descriptor && 'function' !== typeof descriptor) ||
- null === descriptor
- )
- {throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);}
- if (definePropertyFallback)
- {try {
- return definePropertyFallback.call(
- Object,
- object,
- property,
- descriptor
- );
- } catch (exception) {}}
- if (owns(descriptor, 'value'))
- {if (
- supportsAccessors &&
- (lookupGetter(object, property) || lookupSetter(object, property))
- ) {
- var prototype = object.__proto__;
- (object.__proto__ = prototypeOfObject),
- delete object[property],
- (object[property] = descriptor.value),
- (object.__proto__ = prototype);
- } else object[property] = descriptor.value;}
- else {
- if (!supportsAccessors)
- {throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);}
- owns(descriptor, 'get') &&
- defineGetter(object, property, descriptor.get),
- owns(descriptor, 'set') &&
- defineSetter(object, property, descriptor.set);
- }
- return object;
- };
- }
- Object.defineProperties ||
- (Object.defineProperties = function (object, properties) {
- for (let property in properties)
- {owns(properties, property) &&
- Object.defineProperty(object, property, properties[property]);}
- return object;
- }),
- Object.seal ||
- (Object.seal = function (object) {
- return object;
- }),
- Object.freeze ||
- (Object.freeze = function (object) {
- return object;
- });
- try {
- Object.freeze(function () {});
- } catch (exception) {
- Object.freeze = (function (freezeObject) {
- return function (object) {
- return 'function' === typeof object ? object : freezeObject(object);
- };
- }(Object.freeze));
- }
- if (
- (Object.preventExtensions ||
- (Object.preventExtensions = function (object) {
- return object;
- }),
- Object.isSealed ||
- (Object.isSealed = function () {
- return !1;
- }),
- Object.isFrozen ||
- (Object.isFrozen = function () {
- return !1;
- }),
- Object.isExtensible ||
- (Object.isExtensible = function (object) {
- if (Object(object) === object) throw new TypeError();
- for (var name = ''; owns(object, name);) name += '?';
- object[name] = !0;
- let returnValue = owns(object, name);
- return delete object[name], returnValue;
- }),
- !Object.keys)
- ) {
- let hasDontEnumBug = !0,
- dontEnums = [
- 'toString',
- 'toLocaleString',
- 'valueOf',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'constructor',
- ],
- dontEnumsLength = dontEnums.length;
- for (let key in { toString: null }) hasDontEnumBug = !1;
- Object.keys = function (object) {
- if (
- ('object' !== typeof object && 'function' !== typeof object) ||
- null === object
- )
- {throw new TypeError('Object.keys called on a non-object');}
- let keys = [];
- for (let name in object) owns(object, name) && keys.push(name);
- if (hasDontEnumBug)
- {for (var i = 0, ii = dontEnumsLength; ii > i; i++) {
- var dontEnum = dontEnums[i];
- owns(object, dontEnum) && keys.push(dontEnum);
- }}
- return keys;
- };
- }
- Date.now ||
- (Date.now = function () {
- return new Date().getTime();
- });
- let ws = ' \nv\f\r \u2028\u2029';
- if (!String.prototype.trim || ws.trim()) {
- ws = '[' + ws + ']';
- let trimBeginRegexp = RegExp('^' + ws + ws + '*'),
- trimEndRegexp = RegExp(ws + ws + '*$');
- String.prototype.trim = function () {
- return (this + '')
- .replace(trimBeginRegexp, '')
- .replace(trimEndRegexp, '');
- };
- }
- var toObject = function (o) {
- if (null == o) throw new TypeError('can\'t convert ' + o + ' to object');
- return Object(o);
- };
-});
-ace.define(
- 'sense_editor/mode/worker_parser',
- ['require', 'exports', 'module'],
- function () {
- let at, // The index of the current character
- ch, // The current character
- annos, // annotations
- escapee = {
- '"': '"',
- '\\': '\\',
- '/': '/',
- b: '\b',
- f: '\f',
- n: '\n',
- r: '\r',
- t: '\t',
- },
- text,
- annotate = function (type, text) {
- annos.push({ type: type, text: text, at: at });
- },
- error = function (m) {
- throw {
- name: 'SyntaxError',
- message: m,
- at: at,
- text: text,
- };
- },
- reset = function (newAt) {
- ch = text.charAt(newAt);
- at = newAt + 1;
- },
- next = function (c) {
- if (c && c !== ch) {
- error('Expected \'' + c + '\' instead of \'' + ch + '\'');
- }
-
- ch = text.charAt(at);
- at += 1;
- return ch;
- },
- nextUpTo = function (upTo, errorMessage) {
- let currentAt = at,
- i = text.indexOf(upTo, currentAt);
- if (i < 0) {
- error(errorMessage || 'Expected \'' + upTo + '\'');
- }
- reset(i + upTo.length);
- return text.substring(currentAt, i);
- },
- peek = function (offset) {
- return text.charAt(at + offset);
- },
- number = function () {
- let number,
- string = '';
-
- if (ch === '-') {
- string = '-';
- next('-');
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- if (ch === '.') {
- string += '.';
- while (next() && ch >= '0' && ch <= '9') {
- string += ch;
- }
- }
- if (ch === 'e' || ch === 'E') {
- string += ch;
- next();
- if (ch === '-' || ch === '+') {
- string += ch;
- next();
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- }
- number = +string;
- if (isNaN(number)) {
- error('Bad number');
- } else {
- return number;
- }
- },
- string = function () {
- let hex,
- i,
- string = '',
- uffff;
-
- if (ch === '"') {
- // If the current and the next characters are equal to "", empty string or start of triple quoted strings
- if (peek(0) === '"' && peek(1) === '"') {
- // literal
- next('"');
- next('"');
- return nextUpTo('"""', 'failed to find closing \'"""\'');
- } else {
- while (next()) {
- if (ch === '"') {
- next();
- return string;
- } else if (ch === '\\') {
- next();
- if (ch === 'u') {
- uffff = 0;
- for (i = 0; i < 4; i += 1) {
- hex = parseInt(next(), 16);
- if (!isFinite(hex)) {
- break;
- }
- uffff = uffff * 16 + hex;
- }
- string += String.fromCharCode(uffff);
- } else if (typeof escapee[ch] === 'string') {
- string += escapee[ch];
- } else {
- break;
- }
- } else {
- string += ch;
- }
- }
- }
- }
- error('Bad string');
- },
- white = function () {
- while (ch) {
- // Skip whitespace.
- while (ch && ch <= ' ') {
- next();
- }
- // if the current char in iteration is '#' or the char and the next char is equal to '//'
- // we are on the single line comment
- if (ch === '#' || ch === '/' && peek(0) === '/') {
- // Until we are on the new line, skip to the next char
- while (ch && ch !== '\n') {
- next();
- }
- } else if (ch === '/' && peek(0) === '*') {
- // If the chars starts with '/*', we are on the multiline comment
- next();
- next();
- while (ch && !(ch === '*' && peek(0) === '/')) {
- // Until we have closing tags '*/', skip to the next char
- next();
- }
- if (ch) {
- next();
- next();
- }
- } else break;
- }
- },
- strictWhite = function () {
- while (ch && (ch == ' ' || ch == '\t')) {
- next();
- }
- },
- newLine = function () {
- if (ch == '\n') next();
- },
- word = function () {
- switch (ch) {
- case 't':
- next('t');
- next('r');
- next('u');
- next('e');
- return true;
- case 'f':
- next('f');
- next('a');
- next('l');
- next('s');
- next('e');
- return false;
- case 'n':
- next('n');
- next('u');
- next('l');
- next('l');
- return null;
- }
- error('Unexpected \'' + ch + '\'');
- },
- // parses and returns the method
- method = function () {
- switch (ch) {
- case 'g':
- next('g');
- next('e');
- next('t');
- return 'get';
- case 'G':
- next('G');
- next('E');
- next('T');
- return 'GET';
- case 'h':
- next('h');
- next('e');
- next('a');
- next('d');
- return 'head';
- case 'H':
- next('H');
- next('E');
- next('A');
- next('D');
- return 'HEAD';
- case 'd':
- next('d');
- next('e');
- next('l');
- next('e');
- next('t');
- next('e');
- return 'delete';
- case 'D':
- next('D');
- next('E');
- next('L');
- next('E');
- next('T');
- next('E');
- return 'DELETE';
- case 'p':
- next('p');
- switch (ch) {
- case 'a':
- next('a');
- next('t');
- next('c');
- next('h');
- return 'patch';
- case 'u':
- next('u');
- next('t');
- return 'put';
- case 'o':
- next('o');
- next('s');
- next('t');
- return 'post';
- default:
- error('Unexpected \'' + ch + '\'');
- }
- break;
- case 'P':
- next('P');
- switch (ch) {
- case 'A':
- next('A');
- next('T');
- next('C');
- next('H');
- return 'PATCH';
- case 'U':
- next('U');
- next('T');
- return 'PUT';
- case 'O':
- next('O');
- next('S');
- next('T');
- return 'POST';
- default:
- error('Unexpected \'' + ch + '\'');
- }
- break;
- default:
- error('Expected one of GET/POST/PUT/DELETE/HEAD/PATCH');
- }
- },
- value, // Place holder for the value function.
- array = function () {
- const array = [];
-
- if (ch === '[') {
- next('[');
- white();
- if (ch === ']') {
- next(']');
- return array; // empty array
- }
- while (ch) {
- array.push(value());
- white();
- if (ch === ']') {
- next(']');
- return array;
- }
- next(',');
- white();
- }
- }
- error('Bad array');
- },
- object = function () {
- let key,
- object = {};
-
- if (ch === '{') {
- next('{');
- white();
- if (ch === '}') {
- next('}');
- return object; // empty object
- }
- while (ch) {
- key = string();
- white();
- next(':');
- if (Object.hasOwnProperty.call(object, key)) {
- error('Duplicate key "' + key + '"');
- }
- object[key] = value();
- white();
- if (ch === '}') {
- next('}');
- return object;
- }
- next(',');
- white();
- }
- }
- error('Bad object');
- };
-
- value = function () {
- white();
- switch (ch) {
- case '{':
- return object();
- case '[':
- return array();
- case '"':
- return string();
- case '-':
- return number();
- default:
- return ch >= '0' && ch <= '9' ? number() : word();
- }
- };
-
- let url = function () {
- let url = '';
- while (ch && ch != '\n') {
- url += ch;
- next();
- }
- if (url == '') {
- error('Missing url');
- }
- return url;
- },
- request = function () {
- white();
- method();
- strictWhite();
- url();
- strictWhite(); // advance to one new line
- newLine();
- strictWhite();
- if (ch == '{') {
- object();
- }
- // multi doc request
- strictWhite(); // advance to one new line
- newLine();
- strictWhite();
- while (ch == '{') {
- // another object
- object();
- strictWhite();
- newLine();
- strictWhite();
- }
- },
- comment = function () {
- while (ch == '#') {
- while (ch && ch !== '\n') {
- next();
- }
- white();
- }
- },
- multi_request = function () {
- while (ch && ch != '') {
- white();
- if (!ch) {
- continue;
- }
- try {
- comment();
- white();
- if (!ch) {
- continue;
- }
- request();
- white();
- } catch (e) {
- annotate('error', e.message);
- // snap
- const substring = text.substr(at);
- const nextMatch = substring.search(/^POST|HEAD|GET|PUT|DELETE|PATCH/m);
- if (nextMatch < 1) return;
- reset(at + nextMatch);
- }
- }
- };
-
- return function (source, reviver) {
- let result;
-
- text = source;
- at = 0;
- annos = [];
- next();
- multi_request();
- white();
- if (ch) {
- annotate('error', 'Syntax error');
- }
-
- result = { annotations: annos };
-
- return typeof reviver === 'function'
- ? (function walk(holder, key) {
- let k,
- v,
- value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return reviver.call(holder, key, value);
- }({ '': result }, ''))
- : result;
- };
- }
-);
-
-ace.define(
- 'sense_editor/mode/worker',
- [
- 'require',
- 'exports',
- 'module',
- 'ace/lib/oop',
- 'ace/worker/mirror',
- 'sense_editor/mode/worker_parser',
- ],
- function (require, exports) {
- const oop = require('ace/lib/oop');
- const Mirror = require('ace/worker/mirror').Mirror;
- const parse = require('sense_editor/mode/worker_parser');
-
- const SenseWorker = (exports.SenseWorker = function (sender) {
- Mirror.call(this, sender);
- this.setTimeout(200);
- });
-
- oop.inherits(SenseWorker, Mirror);
-
- (function () {
- this.id = 'senseWorker';
- this.onUpdate = function () {
- const value = this.doc.getValue();
- let pos, result;
- try {
- result = parse(value);
- } catch (e) {
- pos = this.charToDocumentPosition(e.at - 1);
- this.sender.emit('error', {
- row: pos.row,
- column: pos.column,
- text: e.message,
- type: 'error',
- });
- return;
- }
- for (let i = 0; i < result.annotations.length; i++) {
- pos = this.charToDocumentPosition(result.annotations[i].at - 1);
- result.annotations[i].row = pos.row;
- result.annotations[i].column = pos.column;
- }
- this.sender.emit('ok', result.annotations);
- };
-
- this.charToDocumentPosition = function (charPos) {
- let i = 0;
- const len = this.doc.getLength();
- const nl = this.doc.getNewLineCharacter().length;
-
- if (!len) {
- return { row: 0, column: 0 };
- }
-
- let lineStart = 0,
- line;
- while (i < len) {
- line = this.doc.getLine(i);
- const lineLength = line.length + nl;
- if (lineStart + lineLength > charPos) {
- return {
- row: i,
- column: charPos - lineStart,
- };
- }
-
- lineStart += lineLength;
- i += 1;
- }
-
- return {
- row: i - 1,
- column: line.length,
- };
- };
- }.call(SenseWorker.prototype));
- }
-);
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/output_tokenization.test.js b/src/plugins/console/public/application/models/legacy_core_editor/output_tokenization.test.js
deleted file mode 100644
index e09bf06e48246..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/output_tokenization.test.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import './legacy_core_editor.test.mocks';
-import $ from 'jquery';
-import RowParser from '../../../lib/row_parser';
-import ace from 'brace';
-import { createReadOnlyAceEditor } from './create_readonly';
-let output;
-const tokenIterator = ace.acequire('ace/token_iterator');
-
-describe('Output Tokenization', () => {
- beforeEach(() => {
- output = createReadOnlyAceEditor(document.querySelector('#ConAppOutput'));
- $(output.container).show();
- });
-
- afterEach(() => {
- $(output.container).hide();
- });
-
- function tokensAsList() {
- const iter = new tokenIterator.TokenIterator(output.getSession(), 0, 0);
- const ret = [];
- let t = iter.getCurrentToken();
- const parser = new RowParser(output);
- if (parser.isEmptyToken(t)) {
- t = parser.nextNonEmptyToken(iter);
- }
- while (t) {
- ret.push({ value: t.value, type: t.type });
- t = parser.nextNonEmptyToken(iter);
- }
-
- return ret;
- }
-
- let testCount = 0;
-
- function tokenTest(tokenList, data) {
- if (data && typeof data !== 'string') {
- data = JSON.stringify(data, null, 3);
- }
-
- test('Token test ' + testCount++, function (done) {
- output.update(data, function () {
- const tokens = tokensAsList();
- const normTokenList = [];
- for (let i = 0; i < tokenList.length; i++) {
- normTokenList.push({ type: tokenList[i++], value: tokenList[i] });
- }
-
- expect(tokens).toEqual(normTokenList);
- done();
- });
- });
- }
-
- tokenTest(
- ['warning', '#! warning', 'comment', '# GET url', 'paren.lparen', '{', 'paren.rparen', '}'],
- '#! warning\n' + '# GET url\n' + '{}'
- );
-
- tokenTest(
- [
- 'comment',
- '# GET url',
- 'paren.lparen',
- '{',
- 'variable',
- '"f"',
- 'punctuation.colon',
- ':',
- 'punctuation.start_triple_quote',
- '"""',
- 'multi_string',
- 'raw',
- 'punctuation.end_triple_quote',
- '"""',
- 'paren.rparen',
- '}',
- ],
- '# GET url\n' + '{ "f": """raw""" }'
- );
-});
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/smart_resize.ts b/src/plugins/console/public/application/models/legacy_core_editor/smart_resize.ts
deleted file mode 100644
index c238e8c6a5da7..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/smart_resize.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { get, throttle } from 'lodash';
-import type { Editor } from 'brace';
-
-// eslint-disable-next-line import/no-default-export
-export default function (editor: Editor) {
- const resize = editor.resize;
-
- const throttledResize = throttle(() => {
- resize.call(editor, false);
-
- // Keep current top line in view when resizing to avoid losing user context
- const userRow = get(throttledResize, 'topRow', 0);
- if (userRow !== 0) {
- editor.renderer.scrollToLine(userRow, false, false, () => {});
- }
- }, 35);
- return throttledResize;
-}
diff --git a/src/plugins/console/public/application/models/legacy_core_editor/theme_sense_dark.js b/src/plugins/console/public/application/models/legacy_core_editor/theme_sense_dark.js
deleted file mode 100644
index fd8e12bf1d703..0000000000000
--- a/src/plugins/console/public/application/models/legacy_core_editor/theme_sense_dark.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import ace from 'brace';
-
-ace.define('ace/theme/sense-dark', ['require', 'exports', 'module'], function (require, exports) {
- exports.isDark = true;
- exports.cssClass = 'ace-sense-dark';
- exports.cssText =
- '.ace-sense-dark .ace_gutter {\
-background: #2e3236;\
-color: #bbbfc2;\
-}\
-.ace-sense-dark .ace_print-margin {\
-width: 1px;\
-background: #555651\
-}\
-.ace-sense-dark .ace_scroller {\
-background-color: #202328;\
-}\
-.ace-sense-dark .ace_content {\
-}\
-.ace-sense-dark .ace_text-layer {\
-color: #F8F8F2\
-}\
-.ace-sense-dark .ace_cursor {\
-border-left: 2px solid #F8F8F0\
-}\
-.ace-sense-dark .ace_overwrite-cursors .ace_cursor {\
-border-left: 0px;\
-border-bottom: 1px solid #F8F8F0\
-}\
-.ace-sense-dark .ace_marker-layer .ace_selection {\
-background: #222\
-}\
-.ace-sense-dark.ace_multiselect .ace_selection.ace_start {\
-box-shadow: 0 0 3px 0px #272822;\
-border-radius: 2px\
-}\
-.ace-sense-dark .ace_marker-layer .ace_step {\
-background: rgb(102, 82, 0)\
-}\
-.ace-sense-dark .ace_marker-layer .ace_bracket {\
-margin: -1px 0 0 -1px;\
-border: 1px solid #49483E\
-}\
-.ace-sense-dark .ace_marker-layer .ace_active-line {\
-background: #202020\
-}\
-.ace-sense-dark .ace_gutter-active-line {\
-background-color: #272727\
-}\
-.ace-sense-dark .ace_marker-layer .ace_selected-word {\
-border: 1px solid #49483E\
-}\
-.ace-sense-dark .ace_invisible {\
-color: #49483E\
-}\
-.ace-sense-dark .ace_entity.ace_name.ace_tag,\
-.ace-sense-dark .ace_keyword,\
-.ace-sense-dark .ace_meta,\
-.ace-sense-dark .ace_storage {\
-color: #F92672\
-}\
-.ace-sense-dark .ace_constant.ace_character,\
-.ace-sense-dark .ace_constant.ace_language,\
-.ace-sense-dark .ace_constant.ace_numeric,\
-.ace-sense-dark .ace_constant.ace_other {\
-color: #AE81FF\
-}\
-.ace-sense-dark .ace_invalid {\
-color: #F8F8F0;\
-background-color: #F92672\
-}\
-.ace-sense-dark .ace_invalid.ace_deprecated {\
-color: #F8F8F0;\
-background-color: #AE81FF\
-}\
-.ace-sense-dark .ace_support.ace_constant,\
-.ace-sense-dark .ace_support.ace_function {\
-color: #66D9EF\
-}\
-.ace-sense-dark .ace_fold {\
-background-color: #A6E22E;\
-border-color: #F8F8F2\
-}\
-.ace-sense-dark .ace_storage.ace_type,\
-.ace-sense-dark .ace_support.ace_class,\
-.ace-sense-dark .ace_support.ace_type {\
-font-style: italic;\
-color: #66D9EF\
-}\
-.ace-sense-dark .ace_entity.ace_name.ace_function,\
-.ace-sense-dark .ace_entity.ace_other.ace_attribute-name,\
-.ace-sense-dark .ace_variable {\
-color: #A6E22E\
-}\
-.ace-sense-dark .ace_variable.ace_parameter {\
-font-style: italic;\
-color: #FD971F\
-}\
-.ace-sense-dark .ace_string {\
-color: #E6DB74\
-}\
-.ace-sense-dark .ace_comment {\
-color: #629755\
-}\
-.ace-sense-dark .ace_markup.ace_underline {\
-text-decoration: underline\
-}\
-.ace-sense-dark .ace_indent-guide {\
-background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQ11D6z7Bq1ar/ABCKBG6g04U2AAAAAElFTkSuQmCC) right repeat-y\
-}';
-
- const dom = require('ace/lib/dom');
- dom.importCssString(exports.cssText, exports.cssClass);
-});
diff --git a/src/plugins/console/public/application/models/sense_editor/__fixtures__/editor_input1.txt b/src/plugins/console/public/application/models/sense_editor/__fixtures__/editor_input1.txt
deleted file mode 100644
index 517f22bd8ad6a..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/__fixtures__/editor_input1.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-GET _search
-{
- "query": { "match_all": {} }
-}
-
-#preceeding comment
-GET _stats?level=shards
-
-#in between comment
-
-PUT index_1/type1/1
-{
- "f": 1
-}
-
-PUT index_1/type1/2
-{
- "f": 2
-}
-
-# comment
-
-
-GET index_1/type1/1/_source?_source_include=f
-
-DELETE index_2
-
-
-POST /_sql?format=txt
-{
- "query": "SELECT prenom FROM claude_index WHERE prenom = 'claude' ",
- "fetch_size": 1
-}
-
-GET ,,/_search?pretty
-
-GET kbn:/api/spaces/space
\ No newline at end of file
diff --git a/src/plugins/console/public/application/models/sense_editor/create.ts b/src/plugins/console/public/application/models/sense_editor/create.ts
deleted file mode 100644
index 9c6c3e38471d5..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/create.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { SenseEditor } from './sense_editor';
-import * as core from '../legacy_core_editor';
-
-export function create(element: HTMLElement) {
- const coreEditor = core.create(element);
- const senseEditor = new SenseEditor(coreEditor);
-
- /**
- * Init the editor
- */
- senseEditor.highlightCurrentRequestsAndUpdateActionBar();
- return senseEditor;
-}
diff --git a/src/plugins/console/public/application/models/sense_editor/curl.ts b/src/plugins/console/public/application/models/sense_editor/curl.ts
deleted file mode 100644
index 9080610a0e8c5..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/curl.ts
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-function detectCURLinLine(line: string) {
- // returns true if text matches a curl request
- return line.match(/^\s*?curl\s+(-X[A-Z]+)?\s*['"]?.*?['"]?(\s*$|\s+?-d\s*?['"])/);
-}
-
-export function detectCURL(text: string) {
- // returns true if text matches a curl request
- if (!text) return false;
- for (const line of text.split('\n')) {
- if (detectCURLinLine(line)) {
- return true;
- }
- }
- return false;
-}
-
-export function parseCURL(text: string) {
- let state = 'NONE';
- const out = [];
- let body: string[] = [];
- let line = '';
- const lines = text.trim().split('\n');
- let matches;
-
- const EmptyLine = /^\s*$/;
- const Comment = /^\s*(?:#|\/{2,})(.*)\n?$/;
- const ExecutionComment = /^\s*#!/;
- const ClosingSingleQuote = /^([^']*)'/;
- const ClosingDoubleQuote = /^((?:[^\\"]|\\.)*)"/;
- const EscapedQuotes = /^((?:[^\\"']|\\.)+)/;
-
- const LooksLikeCurl = /^\s*curl\s+/;
- const CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE|PATCH)/;
-
- const HasProtocol = /[\s"']https?:\/\//;
- const CurlRequestWithProto = /[\s"']https?:\/\/[^\/ ]+\/+([^\s"']+)/;
- const CurlRequestWithoutProto = /[\s"'][^\/ ]+\/+([^\s"']+)/;
- const CurlData = /^.+\s(--data|-d)\s*/;
- const SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE|PATCH)\s+\/?(.+)/;
-
- if (lines.length > 0 && ExecutionComment.test(lines[0])) {
- lines.shift();
- }
-
- function nextLine() {
- if (line.length > 0) {
- return true;
- }
- if (lines.length === 0) {
- return false;
- }
- line = lines.shift()!.replace(/[\r\n]+/g, '\n') + '\n';
- return true;
- }
-
- function unescapeLastBodyEl() {
- const str = body.pop()!.replace(/\\([\\"'])/g, '$1');
- body.push(str);
- }
-
- // Is the next char a single or double quote?
- // If so remove it
- function detectQuote() {
- if (line.substr(0, 1) === "'") {
- line = line.substr(1);
- state = 'SINGLE_QUOTE';
- } else if (line.substr(0, 1) === '"') {
- line = line.substr(1);
- state = 'DOUBLE_QUOTE';
- } else {
- state = 'UNQUOTED';
- }
- }
-
- // Body is finished - append to output with final LF
- function addBodyToOut() {
- if (body.length > 0) {
- out.push(body.join(''));
- body = [];
- }
- state = 'LF';
- out.push('\n');
- }
-
- // If the pattern matches, then the state is about to change,
- // so add the capture to the body and detect the next state
- // Otherwise add the whole line
- function consumeMatching(pattern: string | RegExp) {
- const result = line.match(pattern);
- if (result) {
- body.push(result[1]);
- line = line.substr(result[0].length);
- detectQuote();
- } else {
- body.push(line);
- line = '';
- }
- }
-
- function parseCurlLine() {
- let verb = 'GET';
- let request = '';
- let result;
- if ((result = line.match(CurlVerb))) {
- verb = result[1];
- }
-
- // JS regexen don't support possessive quantifiers, so
- // we need two distinct patterns
- const pattern = HasProtocol.test(line) ? CurlRequestWithProto : CurlRequestWithoutProto;
-
- if ((result = line.match(pattern))) {
- request = result[1];
- }
-
- out.push(verb + ' /' + request + '\n');
-
- if ((result = line.match(CurlData))) {
- line = line.substr(result[0].length);
- detectQuote();
- if (EmptyLine.test(line)) {
- line = '';
- }
- } else {
- state = 'NONE';
- line = '';
- out.push('');
- }
- }
-
- while (nextLine()) {
- if (state === 'SINGLE_QUOTE') {
- consumeMatching(ClosingSingleQuote);
- } else if (state === 'DOUBLE_QUOTE') {
- consumeMatching(ClosingDoubleQuote);
- unescapeLastBodyEl();
- } else if (state === 'UNQUOTED') {
- consumeMatching(EscapedQuotes);
- if (body.length) {
- unescapeLastBodyEl();
- }
- if (state === 'UNQUOTED') {
- addBodyToOut();
- line = '';
- }
- }
-
- // the BODY state (used to match the body of a Sense request)
- // can be terminated early if it encounters
- // a comment or an empty line
- else if (state === 'BODY') {
- if (Comment.test(line) || EmptyLine.test(line)) {
- addBodyToOut();
- } else {
- body.push(line);
- line = '';
- }
- } else if (EmptyLine.test(line)) {
- if (state !== 'LF') {
- out.push('\n');
- state = 'LF';
- }
- line = '';
- } else if ((matches = line.match(Comment))) {
- out.push('#' + matches[1] + '\n');
- state = 'NONE';
- line = '';
- } else if (LooksLikeCurl.test(line)) {
- parseCurlLine();
- } else if ((matches = line.match(SenseLine))) {
- out.push(matches[1] + ' /' + matches[2] + '\n');
- line = '';
- state = 'BODY';
- }
-
- // Nothing else matches, so output with a prefix of ### for debugging purposes
- else {
- out.push('### ' + line);
- line = '';
- }
- }
-
- addBodyToOut();
- return out.join('').trim();
-}
diff --git a/src/plugins/console/public/application/models/sense_editor/index.ts b/src/plugins/console/public/application/models/sense_editor/index.ts
deleted file mode 100644
index 2bd44988dc02f..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/index.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-export * from './create';
-export * from '../legacy_core_editor/create_readonly';
-export { MODE } from '../../../lib/row_parser';
-export { SenseEditor } from './sense_editor';
-export { getEndpointFromPosition } from '../../../lib/autocomplete/get_endpoint_from_position';
diff --git a/src/plugins/console/public/application/models/sense_editor/integration.test.js b/src/plugins/console/public/application/models/sense_editor/integration.test.js
deleted file mode 100644
index bed83293e31d6..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/integration.test.js
+++ /dev/null
@@ -1,1279 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import './sense_editor.test.mocks';
-import { create } from './create';
-import _ from 'lodash';
-import $ from 'jquery';
-
-import * as kb from '../../../lib/kb/kb';
-import { AutocompleteInfo, setAutocompleteInfo } from '../../../services';
-import { httpServiceMock } from '@kbn/core-http-browser-mocks';
-import { StorageMock } from '../../../services/storage.mock';
-import { SettingsMock } from '../../../services/settings.mock';
-
-describe('Integration', () => {
- let senseEditor;
- let autocompleteInfo;
-
- beforeEach(() => {
- // Set up our document body
- document.body.innerHTML =
- '';
-
- senseEditor = create(document.querySelector('#ConAppEditor'));
- $(senseEditor.getCoreEditor().getContainer()).show();
- senseEditor.autocomplete._test.removeChangeListener();
- autocompleteInfo = new AutocompleteInfo();
-
- const httpMock = httpServiceMock.createSetupContract();
- const storage = new StorageMock({}, 'test');
- const settingsMock = new SettingsMock(storage);
-
- settingsMock.getAutocomplete.mockReturnValue({ fields: true });
-
- autocompleteInfo.mapping.setup(httpMock, settingsMock);
-
- setAutocompleteInfo(autocompleteInfo);
- });
- afterEach(() => {
- $(senseEditor.getCoreEditor().getContainer()).hide();
- senseEditor.autocomplete._test.addChangeListener();
- autocompleteInfo = null;
- setAutocompleteInfo(null);
- });
-
- function processContextTest(data, mapping, kbSchemes, requestLine, testToRun) {
- test(testToRun.name, function (done) {
- let lineOffset = 0; // add one for the extra method line
- let editorValue = data;
- if (requestLine != null) {
- if (data != null) {
- editorValue = requestLine + '\n' + data;
- lineOffset = 1;
- } else {
- editorValue = requestLine;
- }
- }
-
- testToRun.cursor.lineNumber += lineOffset;
-
- autocompleteInfo.clear();
- autocompleteInfo.mapping.loadMappings(mapping);
- const json = {};
- json[test.name] = kbSchemes || {};
- const testApi = kb._test.loadApisFromJson(json);
- if (kbSchemes) {
- // if (kbSchemes.globals) {
- // $.each(kbSchemes.globals, function (parent, rules) {
- // testApi.addGlobalAutocompleteRules(parent, rules);
- // });
- // }
- if (kbSchemes.endpoints) {
- $.each(kbSchemes.endpoints, function (endpoint, scheme) {
- testApi.addEndpointDescription(endpoint, scheme);
- });
- }
- }
- kb._test.setActiveApi(testApi);
- const { cursor } = testToRun;
- senseEditor.update(editorValue, true).then(() => {
- senseEditor.getCoreEditor().moveCursorToPosition(cursor);
- // allow ace rendering to move cursor so it will be seen during test - handy for debugging.
- //setTimeout(function () {
- senseEditor.completer = {
- base: {},
- changeListener: function () {},
- }; // mimic auto complete
-
- senseEditor.autocomplete._test.getCompletions(
- senseEditor,
- null,
- cursor,
- '',
- function (err, terms) {
- if (testToRun.assertThrows) {
- done();
- return;
- }
-
- if (err) {
- throw err;
- }
-
- if (testToRun.no_context) {
- expect(!terms || terms.length === 0).toBeTruthy();
- } else {
- expect(terms).not.toBeNull();
- expect(terms.length).toBeGreaterThan(0);
- }
-
- if (!terms || terms.length === 0) {
- done();
- return;
- }
-
- if (testToRun.autoCompleteSet) {
- const expectedTerms = _.map(testToRun.autoCompleteSet, function (t) {
- if (typeof t !== 'object') {
- t = { name: t };
- }
- return t;
- });
- if (terms.length !== expectedTerms.length) {
- expect(_.map(terms, 'name')).toEqual(_.map(expectedTerms, 'name'));
- } else {
- const filteredActualTerms = _.map(terms, function (actualTerm, i) {
- const expectedTerm = expectedTerms[i];
- const filteredTerm = {};
- _.each(expectedTerm, function (v, p) {
- filteredTerm[p] = actualTerm[p];
- });
- return filteredTerm;
- });
- expect(filteredActualTerms).toEqual(expectedTerms);
- }
- }
-
- const context = terms[0].context;
- const {
- cursor: { lineNumber, column },
- } = testToRun;
- senseEditor.autocomplete._test.addReplacementInfoToContext(
- context,
- { lineNumber, column },
- terms[0].value
- );
-
- function ac(prop, propTest) {
- if (typeof testToRun[prop] !== 'undefined') {
- if (propTest) {
- propTest(context[prop], testToRun[prop], prop);
- } else {
- expect(context[prop]).toEqual(testToRun[prop]);
- }
- }
- }
-
- function posCompare(actual, expected) {
- expect(actual.lineNumber).toEqual(expected.lineNumber + lineOffset);
- expect(actual.column).toEqual(expected.column);
- }
-
- function rangeCompare(actual, expected, name) {
- posCompare(actual.start, expected.start, name + '.start');
- posCompare(actual.end, expected.end, name + '.end');
- }
-
- ac('prefixToAdd');
- ac('suffixToAdd');
- ac('addTemplate');
- ac('textBoxPosition', posCompare);
- ac('rangeToReplace', rangeCompare);
- done();
- },
- { setAnnotation: () => {}, removeAnnotation: () => {} }
- );
- });
- });
- }
-
- function contextTests(data, mapping, kbSchemes, requestLine, tests) {
- if (data != null && typeof data !== 'string') {
- data = JSON.stringify(data, null, 3);
- }
- for (let t = 0; t < tests.length; t++) {
- processContextTest(data, mapping, kbSchemes, requestLine, tests[t]);
- }
- }
-
- const SEARCH_KB = {
- endpoints: {
- _search: {
- methods: ['GET', 'POST'],
- patterns: ['{index}/_search', '_search'],
- data_autocomplete_rules: {
- query: {
- match_all: {},
- term: { '{field}': { __template: { f: 1 } } },
- },
- size: {},
- facets: {
- __template: {
- FIELD: {},
- },
- '*': { terms: { field: '{field}' } },
- },
- },
- },
- },
- };
-
- const MAPPING = {
- index1: {
- properties: {
- 'field1.1.1': { type: 'string' },
- 'field1.1.2': { type: 'string' },
- },
- },
- index2: {
- properties: {
- 'field2.1.1': { type: 'string' },
- 'field2.1.2': { type: 'string' },
- },
- },
- };
-
- contextTests({}, MAPPING, SEARCH_KB, 'POST _search', [
- {
- name: 'Empty doc',
- cursor: { lineNumber: 1, column: 2 },
- initialValue: '',
- addTemplate: true,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 1, column: 2 },
- end: { lineNumber: 1, column: 2 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- ]);
-
- contextTests({}, MAPPING, SEARCH_KB, 'POST _no_context', [
- {
- name: 'Missing KB',
- cursor: { lineNumber: 1, column: 2 },
- no_context: true,
- },
- ]);
-
- contextTests(
- {
- query: {
- f: 1,
- },
- },
- MAPPING,
- {
- globals: {
- query: {
- t1: 2,
- },
- },
- endpoints: {},
- },
- 'POST _no_context',
- [
- {
- name: 'Missing KB - global auto complete',
- cursor: { lineNumber: 3, column: 6 },
- autoCompleteSet: ['t1'],
- },
- ]
- );
-
- contextTests(
- {
- query: {
- field: 'something',
- },
- facets: {},
- size: 20,
- },
- MAPPING,
- SEARCH_KB,
- 'POST _search',
- [
- {
- name: 'existing dictionary key, no template',
- cursor: { lineNumber: 2, column: 6 },
- initialValue: 'query',
- addTemplate: false,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 2, column: 4 },
- end: { lineNumber: 2, column: 11 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- {
- name: 'existing inner dictionary key',
- cursor: { lineNumber: 3, column: 8 },
- initialValue: 'field',
- addTemplate: false,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 3, column: 7 },
- end: { lineNumber: 3, column: 14 },
- },
- autoCompleteSet: ['match_all', 'term'],
- },
- {
- name: 'existing dictionary key, yes template',
- cursor: { lineNumber: 5, column: 8 },
- initialValue: 'facets',
- addTemplate: true,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 5, column: 4 },
- end: { lineNumber: 5, column: 16 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- {
- name: 'ignoring meta keys',
- cursor: { lineNumber: 5, column: 15 },
- no_context: true,
- },
- ]
- );
-
- contextTests(
- '{\n' +
- ' "query": {\n' +
- ' "field": "something"\n' +
- ' },\n' +
- ' "facets": {},\n' +
- ' "size": 20\n' +
- '}',
- MAPPING,
- SEARCH_KB,
- 'POST _search',
- [
- {
- name: 'trailing comma, end of line',
- cursor: { lineNumber: 5, column: 17 },
- initialValue: '',
- addTemplate: true,
- prefixToAdd: '',
- suffixToAdd: ', ',
- rangeToReplace: {
- start: { lineNumber: 5, column: 17 },
- end: { lineNumber: 5, column: 17 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- {
- name: 'trailing comma, beginning of line',
- cursor: { lineNumber: 6, column: 2 },
- initialValue: '',
- addTemplate: true,
- prefixToAdd: '',
- suffixToAdd: ', ',
- rangeToReplace: {
- start: { lineNumber: 6, column: 2 },
- end: { lineNumber: 6, column: 2 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- {
- name: 'prefix comma, end of line',
- cursor: { lineNumber: 7, column: 1 },
- initialValue: '',
- addTemplate: true,
- prefixToAdd: ',\n',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 6, column: 14 },
- end: { lineNumber: 7, column: 1 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- ]
- );
-
- contextTests(
- {
- object: 1,
- array: 1,
- value_one_of: 1,
- value: 2,
- something_else: 5,
- },
- MAPPING,
- {
- endpoints: {
- _test: {
- patterns: ['_test'],
- data_autocomplete_rules: {
- object: { bla: 1 },
- array: [1],
- value_one_of: { __one_of: [1, 2] },
- value: 3,
- '*': { __one_of: [4, 5] },
- },
- },
- },
- },
- 'GET _test',
- [
- {
- name: 'not matching object when { is not opened',
- cursor: { lineNumber: 2, column: 13 },
- initialValue: '',
- autoCompleteSet: ['{'],
- },
- {
- name: 'not matching array when [ is not opened',
- cursor: { lineNumber: 3, column: 13 },
- initialValue: '',
- autoCompleteSet: ['['],
- },
- {
- name: 'matching value with one_of',
- cursor: { lineNumber: 4, column: 20 },
- initialValue: '',
- autoCompleteSet: [1, 2],
- },
- {
- name: 'matching value',
- cursor: { lineNumber: 5, column: 13 },
- initialValue: '',
- autoCompleteSet: [3],
- },
- {
- name: 'matching any value with one_of',
- cursor: { lineNumber: 6, column: 22 },
- initialValue: '',
- autoCompleteSet: [4, 5],
- },
- ]
- );
-
- contextTests(
- {
- query: {
- field: 'something',
- },
- facets: {
- name: {},
- },
- size: 20,
- },
- MAPPING,
- SEARCH_KB,
- 'GET _search',
- [
- {
- name: '* matching everything',
- cursor: { lineNumber: 6, column: 16 },
- initialValue: '',
- addTemplate: true,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 6, column: 16 },
- end: { lineNumber: 6, column: 16 },
- },
- autoCompleteSet: [{ name: 'terms', meta: 'API' }],
- },
- ]
- );
-
- contextTests(
- {
- index: '123',
- },
- MAPPING,
- {
- endpoints: {
- _test: {
- patterns: ['_test'],
- data_autocomplete_rules: {
- index: '{index}',
- },
- },
- },
- },
- 'GET _test',
- [
- {
- name: '{index} matching',
- cursor: { lineNumber: 2, column: 16 },
- autoCompleteSet: [
- { name: 'index1', meta: 'index' },
- { name: 'index2', meta: 'index' },
- ],
- },
- ]
- );
-
- function tt(term, template, meta) {
- term = { name: term, template: template };
- if (meta) {
- term.meta = meta;
- }
- return term;
- }
-
- contextTests(
- {
- array: ['a'],
- oneof: '1',
- },
- MAPPING,
- {
- endpoints: {
- _endpoint: {
- patterns: ['_endpoint'],
- data_autocomplete_rules: {
- array: ['a', 'b'],
- number: 1,
- object: {},
- fixed: { __template: { a: 1 } },
- oneof: { __one_of: ['o1', 'o2'] },
- },
- },
- },
- },
- 'GET _endpoint',
- [
- {
- name: 'Templates 1',
- cursor: { lineNumber: 2, column: 1 },
- autoCompleteSet: [
- tt('array', []),
- tt('fixed', { a: 1 }),
- tt('number', 1),
- tt('object', {}),
- tt('oneof', 'o1'),
- ],
- },
- {
- name: 'Templates - one off',
- cursor: { lineNumber: 5, column: 13 },
- autoCompleteSet: [tt('o1'), tt('o2')],
- },
- ]
- );
-
- contextTests(
- {
- string: 'value',
- context: {},
- },
- MAPPING,
- {
- endpoints: {
- _endpoint: {
- patterns: ['_endpoint'],
- data_autocomplete_rules: {
- context: {
- __one_of: [
- {
- __condition: {
- lines_regex: 'value',
- },
- match: {},
- },
- {
- __condition: {
- lines_regex: 'other',
- },
- no_match: {},
- },
- { always: {} },
- ],
- },
- },
- },
- },
- },
- 'GET _endpoint',
- [
- {
- name: 'Conditionals',
- cursor: { lineNumber: 3, column: 16 },
- autoCompleteSet: [tt('always', {}), tt('match', {})],
- },
- ]
- );
-
- contextTests(
- {
- any_of_numbers: [1],
- any_of_obj: [
- {
- a: 1,
- },
- ],
- any_of_mixed: [
- {
- a: 1,
- },
- 2,
- ],
- },
- MAPPING,
- {
- endpoints: {
- _endpoint: {
- patterns: ['_endpoint'],
- data_autocomplete_rules: {
- any_of_numbers: { __template: [1, 2], __any_of: [1, 2, 3] },
- any_of_obj: {
- __template: [{ c: 1 }],
- __any_of: [{ a: 1, b: 2 }, { c: 1 }],
- },
- any_of_mixed: {
- __any_of: [{ a: 1 }, 3],
- },
- },
- },
- },
- },
- 'GET _endpoint',
- [
- {
- name: 'Any of - templates',
- cursor: { lineNumber: 2, column: 1 },
- autoCompleteSet: [
- tt('any_of_mixed', []),
- tt('any_of_numbers', [1, 2]),
- tt('any_of_obj', [{ c: 1 }]),
- ],
- },
- {
- name: 'Any of - numbers',
- cursor: { lineNumber: 3, column: 3 },
- autoCompleteSet: [1, 2, 3],
- },
- {
- name: 'Any of - object',
- cursor: { lineNumber: 7, column: 3 },
- autoCompleteSet: [tt('a', 1), tt('b', 2), tt('c', 1)],
- },
- {
- name: 'Any of - mixed - obj',
- cursor: { lineNumber: 12, column: 3 },
- autoCompleteSet: [tt('a', 1)],
- },
- {
- name: 'Any of - mixed - both',
- cursor: { lineNumber: 14, column: 3 },
- autoCompleteSet: [tt(3), tt('{')],
- },
- ]
- );
-
- contextTests(
- {},
- MAPPING,
- {
- endpoints: {
- _endpoint: {
- patterns: ['_endpoint'],
- data_autocomplete_rules: {
- query: '',
- },
- },
- },
- },
- 'GET _endpoint',
- [
- {
- name: 'Empty string as default',
- cursor: { lineNumber: 1, column: 2 },
- autoCompleteSet: [tt('query', '')],
- },
- ]
- );
-
- // NOTE: This test emits "error while getting completion terms Error: failed to resolve link
- // [GLOBAL.broken]: Error: failed to resolve global components for ['broken']". but that's
- // expected.
- contextTests(
- {
- a: {
- b: {},
- c: {},
- d: {
- t1a: {},
- },
- e: {},
- f: [{}],
- g: {},
- h: {},
- },
- },
- MAPPING,
- {
- globals: {
- gtarget: {
- t1: 2,
- t1a: {
- __scope_link: '.',
- },
- },
- },
- endpoints: {
- _current: {
- patterns: ['_current'],
- data_autocomplete_rules: {
- a: {
- b: {
- __scope_link: '.a',
- },
- c: {
- __scope_link: 'ext.target',
- },
- d: {
- __scope_link: 'GLOBAL.gtarget',
- },
- e: {
- __scope_link: 'ext',
- },
- f: [
- {
- __scope_link: 'ext.target',
- },
- ],
- g: {
- __scope_link: function () {
- return {
- a: 1,
- b: 2,
- };
- },
- },
- h: {
- __scope_link: 'GLOBAL.broken',
- },
- },
- },
- },
- ext: {
- patterns: ['ext'],
- data_autocomplete_rules: {
- target: {
- t2: 1,
- },
- },
- },
- },
- },
- 'GET _current',
- [
- {
- name: 'Relative scope link test',
- cursor: { lineNumber: 3, column: 13 },
- autoCompleteSet: [
- tt('b', {}),
- tt('c', {}),
- tt('d', {}),
- tt('e', {}),
- tt('f', [{}]),
- tt('g', {}),
- tt('h', {}),
- ],
- },
- {
- name: 'External scope link test',
- cursor: { lineNumber: 4, column: 13 },
- autoCompleteSet: [tt('t2', 1)],
- },
- {
- name: 'Global scope link test',
- cursor: { lineNumber: 5, column: 13 },
- autoCompleteSet: [tt('t1', 2), tt('t1a', {})],
- },
- {
- name: 'Global scope link with an internal scope link',
- cursor: { lineNumber: 6, column: 18 },
- autoCompleteSet: [tt('t1', 2), tt('t1a', {})],
- },
- {
- name: 'Entire endpoint scope link test',
- cursor: { lineNumber: 8, column: 13 },
- autoCompleteSet: [tt('target', {})],
- },
- {
- name: 'A scope link within an array',
- cursor: { lineNumber: 10, column: 11 },
- autoCompleteSet: [tt('t2', 1)],
- },
- {
- name: 'A function based scope link',
- cursor: { lineNumber: 12, column: 13 },
- autoCompleteSet: [tt('a', 1), tt('b', 2)],
- },
- {
- name: 'A global scope link with wrong link',
- cursor: { lineNumber: 13, column: 13 },
- assertThrows: /broken/,
- },
- ]
- );
-
- contextTests(
- {},
- MAPPING,
- {
- globals: {
- gtarget: {
- t1: 2,
- },
- },
- endpoints: {
- _current: {
- patterns: ['_current'],
- id: 'GET _current',
- data_autocomplete_rules: {
- __scope_link: 'GLOBAL.gtarget',
- },
- },
- },
- },
- 'GET _current',
- [
- {
- name: 'Top level scope link',
- cursor: { lineNumber: 1, column: 2 },
- autoCompleteSet: [tt('t1', 2)],
- },
- ]
- );
-
- contextTests(
- {
- a: {},
- },
- MAPPING,
- {
- endpoints: {
- _endpoint: {
- patterns: ['_endpoint'],
- data_autocomplete_rules: {
- a: {},
- b: {},
- },
- },
- },
- },
- 'GET _endpoint',
- [
- {
- name: 'Path after empty object',
- cursor: { lineNumber: 2, column: 11 },
- autoCompleteSet: ['a', 'b'],
- },
- ]
- );
-
- contextTests(
- {
- '': {},
- },
- MAPPING,
- SEARCH_KB,
- 'POST _search',
- [
- {
- name: 'Replace an empty string',
- cursor: { lineNumber: 2, column: 5 },
- rangeToReplace: {
- start: { lineNumber: 2, column: 4 },
- end: { lineNumber: 2, column: 10 },
- },
- },
- ]
- );
-
- contextTests(
- {
- a: [
- {
- c: {},
- },
- ],
- },
- MAPPING,
- {
- endpoints: {
- _endpoint: {
- patterns: ['_endpoint'],
- data_autocomplete_rules: {
- a: [{ b: 1 }],
- },
- },
- },
- },
- 'GET _endpoint',
- [
- {
- name: 'List of objects - internal autocomplete',
- cursor: { lineNumber: 4, column: 11 },
- autoCompleteSet: ['b'],
- },
- {
- name: 'List of objects - external template',
- cursor: { lineNumber: 1, column: 2 },
- autoCompleteSet: [tt('a', [{}])],
- },
- ]
- );
-
- contextTests(
- {
- query: {
- term: {
- field: 'something',
- },
- },
- facets: {
- test: {
- terms: {
- field: 'test',
- },
- },
- },
- size: 20,
- },
- MAPPING,
- SEARCH_KB,
- 'POST index1/_search',
- [
- {
- name: 'Field completion as scope',
- cursor: { lineNumber: 4, column: 11 },
- autoCompleteSet: [
- tt('field1.1.1', { f: 1 }, 'string'),
- tt('field1.1.2', { f: 1 }, 'string'),
- ],
- },
- {
- name: 'Field completion as value',
- cursor: { lineNumber: 10, column: 24 },
- autoCompleteSet: [
- { name: 'field1.1.1', meta: 'string' },
- { name: 'field1.1.2', meta: 'string' },
- ],
- },
- ]
- );
-
- // NOTE: This test emits "Can't extract a valid url token path", but that's expected.
- contextTests('POST _search\n', MAPPING, SEARCH_KB, null, [
- {
- name: 'initial doc start',
- cursor: { lineNumber: 2, column: 1 },
- autoCompleteSet: ['{'],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(
- '{\n' + ' "query": {} \n' + '}\n' + '\n' + '\n',
- MAPPING,
- SEARCH_KB,
- 'POST _search',
- [
- {
- name: 'Cursor rows after request end',
- cursor: { lineNumber: 5, column: 1 },
- autoCompleteSet: ['GET', 'PUT', 'POST', 'DELETE', 'HEAD', 'PATCH'],
- prefixToAdd: '',
- suffixToAdd: ' ',
- },
- {
- name: 'Cursor just after request end',
- cursor: { lineNumber: 3, column: 2 },
- no_context: true,
- },
- ]
- );
-
- const CLUSTER_KB = {
- endpoints: {
- _search: {
- patterns: ['_search', '{index}/_search'],
- url_params: {
- search_type: ['count', 'query_then_fetch'],
- scroll: '10m',
- },
- methods: ['GET'],
- data_autocomplete_rules: {},
- },
- '_cluster/stats': {
- patterns: ['_cluster/stats'],
- indices_mode: 'none',
- data_autocomplete_rules: {},
- methods: ['GET'],
- },
- '_cluster/nodes/stats': {
- patterns: ['_cluster/nodes/stats'],
- data_autocomplete_rules: {},
- methods: ['GET'],
- },
- },
- };
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _cluster', [
- {
- name: 'Endpoints with slashes - no slash',
- cursor: { lineNumber: 1, column: 9 },
- autoCompleteSet: ['_cluster/nodes/stats', '_cluster/stats', '_search', 'index1', 'index2'],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _cluster/', [
- {
- name: 'Endpoints with slashes - before slash',
- cursor: { lineNumber: 1, column: 8 },
- autoCompleteSet: ['_cluster/nodes/stats', '_cluster/stats', '_search', 'index1', 'index2'],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- {
- name: 'Endpoints with slashes - on slash',
- cursor: { lineNumber: 1, column: 13 },
- autoCompleteSet: ['_cluster/nodes/stats', '_cluster/stats', '_search', 'index1', 'index2'],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- {
- name: 'Endpoints with slashes - after slash',
- cursor: { lineNumber: 1, column: 14 },
- autoCompleteSet: ['nodes/stats', 'stats'],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _cluster/no', [
- {
- name: 'Endpoints with slashes - after slash',
- cursor: { lineNumber: 1, column: 15 },
- autoCompleteSet: [
- { name: 'nodes/stats', meta: 'endpoint' },
- { name: 'stats', meta: 'endpoint' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- initialValue: 'no',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _cluster/nodes/st', [
- {
- name: 'Endpoints with two slashes',
- cursor: { lineNumber: 1, column: 21 },
- autoCompleteSet: ['stats'],
- prefixToAdd: '',
- suffixToAdd: '',
- initialValue: 'st',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET ', [
- {
- name: 'Immediately after space + method',
- cursor: { lineNumber: 1, column: 5 },
- autoCompleteSet: [
- { name: '_cluster/nodes/stats', meta: 'endpoint' },
- { name: '_cluster/stats', meta: 'endpoint' },
- { name: '_search', meta: 'endpoint' },
- { name: 'index1', meta: 'index' },
- { name: 'index2', meta: 'index' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- initialValue: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET cl', [
- {
- name: 'Endpoints by subpart GET',
- cursor: { lineNumber: 1, column: 7 },
- autoCompleteSet: [
- { name: '_cluster/nodes/stats', meta: 'endpoint' },
- { name: '_cluster/stats', meta: 'endpoint' },
- { name: '_search', meta: 'endpoint' },
- { name: 'index1', meta: 'index' },
- { name: 'index2', meta: 'index' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- initialValue: 'cl',
- method: 'GET',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'POST cl', [
- {
- name: 'Endpoints by subpart POST',
- cursor: { lineNumber: 1, column: 8 },
- no_context: true,
- prefixToAdd: '',
- suffixToAdd: '',
- initialValue: 'cl',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _search?', [
- {
- name: 'Params just after ?',
- cursor: { lineNumber: 1, column: 13 },
- autoCompleteSet: [
- { name: 'filter_path', meta: 'param', insertValue: 'filter_path=' },
- { name: 'format', meta: 'param', insertValue: 'format=' },
- { name: 'pretty', meta: 'flag' },
- { name: 'scroll', meta: 'param', insertValue: 'scroll=' },
- { name: 'search_type', meta: 'param', insertValue: 'search_type=' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _search?format=', [
- {
- name: 'Params values',
- cursor: { lineNumber: 1, column: 20 },
- autoCompleteSet: [
- { name: 'json', meta: 'format' },
- { name: 'yaml', meta: 'format' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _search?format=yaml&', [
- {
- name: 'Params after amp',
- cursor: { lineNumber: 1, column: 25 },
- autoCompleteSet: [
- { name: 'filter_path', meta: 'param', insertValue: 'filter_path=' },
- { name: 'format', meta: 'param', insertValue: 'format=' },
- { name: 'pretty', meta: 'flag' },
- { name: 'scroll', meta: 'param', insertValue: 'scroll=' },
- { name: 'search_type', meta: 'param', insertValue: 'search_type=' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _search?format=yaml&search', [
- {
- name: 'Params on existing param',
- cursor: { lineNumber: 1, column: 27 },
- rangeToReplace: {
- start: { lineNumber: 1, column: 25 },
- end: { lineNumber: 1, column: 31 },
- },
- autoCompleteSet: [
- { name: 'filter_path', meta: 'param', insertValue: 'filter_path=' },
- { name: 'format', meta: 'param', insertValue: 'format=' },
- { name: 'pretty', meta: 'flag' },
- { name: 'scroll', meta: 'param', insertValue: 'scroll=' },
- { name: 'search_type', meta: 'param', insertValue: 'search_type=' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _search?format=yaml&search_type=cou', [
- {
- name: 'Params on existing value',
- cursor: { lineNumber: 1, column: 38 },
- rangeToReplace: {
- start: { lineNumber: 1, column: 37 },
- end: { lineNumber: 1, column: 40 },
- },
- autoCompleteSet: [
- { name: 'count', meta: 'search_type' },
- { name: 'query_then_fetch', meta: 'search_type' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(null, MAPPING, CLUSTER_KB, 'GET _search?format=yaml&search_type=cou', [
- {
- name: 'Params on just after = with existing value',
- cursor: { lineNumber: 1, column: 37 },
- rangeToReplace: {
- start: { lineNumber: 1, column: 37 },
- end: { lineNumber: 1, column: 37 },
- },
- autoCompleteSet: [
- { name: 'count', meta: 'search_type' },
- { name: 'query_then_fetch', meta: 'search_type' },
- ],
- prefixToAdd: '',
- suffixToAdd: '',
- },
- ]);
-
- contextTests(
- {
- query: {
- field: 'something',
- },
- facets: {},
- size: 20,
- },
- MAPPING,
- SEARCH_KB,
- 'POST http://somehost/_search',
- [
- {
- name: 'fullurl - existing dictionary key, no template',
- cursor: { lineNumber: 2, column: 7 },
- initialValue: 'query',
- addTemplate: false,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 2, column: 4 },
- end: { lineNumber: 2, column: 11 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- {
- name: 'fullurl - existing inner dictionary key',
- cursor: { lineNumber: 3, column: 8 },
- initialValue: 'field',
- addTemplate: false,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 3, column: 7 },
- end: { lineNumber: 3, column: 14 },
- },
- autoCompleteSet: ['match_all', 'term'],
- },
- {
- name: 'fullurl - existing dictionary key, yes template',
- cursor: { lineNumber: 5, column: 8 },
- initialValue: 'facets',
- addTemplate: true,
- prefixToAdd: '',
- suffixToAdd: '',
- rangeToReplace: {
- start: { lineNumber: 5, column: 4 },
- end: { lineNumber: 5, column: 16 },
- },
- autoCompleteSet: ['facets', 'query', 'size'],
- },
- ]
- );
-});
diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js
deleted file mode 100644
index 19d782f1b8e87..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js
+++ /dev/null
@@ -1,641 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import './sense_editor.test.mocks';
-
-import $ from 'jquery';
-import _ from 'lodash';
-import { URL } from 'url';
-
-import { create } from './create';
-import { XJson } from '@kbn/es-ui-shared-plugin/public';
-import editorInput1 from './__fixtures__/editor_input1.txt';
-import { setStorage, createStorage } from '../../../services';
-
-const { collapseLiteralStrings } = XJson;
-
-describe('Editor', () => {
- let input;
- let oldUrl;
- let olldWindow;
- let storage;
-
- beforeEach(function () {
- // Set up our document body
- document.body.innerHTML = ``;
-
- input = create(document.querySelector('#ConAppEditor'));
- $(input.getCoreEditor().getContainer()).show();
- input.autocomplete._test.removeChangeListener();
- oldUrl = global.URL;
- olldWindow = { ...global.window };
- global.URL = URL;
- Object.defineProperty(global, 'window', {
- value: Object.create(window),
- writable: true,
- });
- Object.defineProperty(window, 'location', {
- value: {
- origin: 'http://localhost:5620',
- },
- });
- storage = createStorage({
- engine: global.window.localStorage,
- prefix: 'console_test',
- });
- setStorage(storage);
- });
- afterEach(function () {
- global.URL = oldUrl;
- global.window = olldWindow;
- $(input.getCoreEditor().getContainer()).hide();
- input.autocomplete._test.addChangeListener();
- setStorage(null);
- });
-
- let testCount = 0;
-
- const callWithEditorMethod = (editorMethod, fn) => async (done) => {
- const results = await input[editorMethod]();
- fn(results, done);
- };
-
- function utilsTest(name, prefix, data, testToRun) {
- const id = testCount++;
- if (typeof data === 'function') {
- testToRun = data;
- data = null;
- }
- if (data && typeof data !== 'string') {
- data = JSON.stringify(data, null, 3);
- }
- if (data) {
- if (prefix) {
- data = prefix + '\n' + data;
- }
- } else {
- data = prefix;
- }
-
- test('Utils test ' + id + ' : ' + name, function (done) {
- input.update(data, true).then(() => {
- testToRun(done);
- });
- });
- }
-
- function compareRequest(requests, expected) {
- if (!Array.isArray(requests)) {
- requests = [requests];
- expected = [expected];
- }
-
- _.each(requests, function (r) {
- delete r.range;
- });
- expect(requests).toEqual(expected);
- }
-
- const simpleRequest = {
- prefix: 'POST _search',
- data: ['{', ' "query": { "match_all": {} }', '}'].join('\n'),
- };
-
- const singleLineRequest = {
- prefix: 'POST _search',
- data: '{ "query": { "match_all": {} } }',
- };
-
- const getRequestNoData = {
- prefix: 'GET _stats',
- };
-
- const multiDocRequest = {
- prefix: 'POST _bulk',
- data_as_array: ['{ "index": { "_index": "index", "_type":"type" } }', '{ "field": 1 }'],
- };
- multiDocRequest.data = multiDocRequest.data_as_array.join('\n');
-
- utilsTest(
- 'simple request range',
- simpleRequest.prefix,
- simpleRequest.data,
- callWithEditorMethod('getRequestRange', (range, done) => {
- compareRequest(range, {
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 4, column: 2 },
- });
- done();
- })
- );
-
- utilsTest(
- 'simple request data',
- simpleRequest.prefix,
- simpleRequest.data,
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'POST',
- url: '_search',
- data: [simpleRequest.data],
- };
- compareRequest(request, expected);
- done();
- })
- );
-
- utilsTest(
- 'simple request range, prefixed with spaces',
- ' ' + simpleRequest.prefix,
- simpleRequest.data,
- callWithEditorMethod('getRequestRange', (range, done) => {
- expect(range).toEqual({
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 4, column: 2 },
- });
- done();
- })
- );
-
- utilsTest(
- 'simple request data, prefixed with spaces',
- ' ' + simpleRequest.prefix,
- simpleRequest.data,
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'POST',
- url: '_search',
- data: [simpleRequest.data],
- };
-
- compareRequest(request, expected);
- done();
- })
- );
-
- utilsTest(
- 'simple request range, suffixed with spaces',
- simpleRequest.prefix + ' ',
- simpleRequest.data + ' ',
- callWithEditorMethod('getRequestRange', (range, done) => {
- compareRequest(range, {
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 4, column: 2 },
- });
- done();
- })
- );
-
- utilsTest(
- 'simple request data, suffixed with spaces',
- simpleRequest.prefix + ' ',
- simpleRequest.data + ' ',
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'POST',
- url: '_search',
- data: [simpleRequest.data],
- };
-
- compareRequest(request, expected);
- done();
- })
- );
-
- utilsTest(
- 'single line request range',
- singleLineRequest.prefix,
- singleLineRequest.data,
- callWithEditorMethod('getRequestRange', (range, done) => {
- compareRequest(range, {
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 2, column: 33 },
- });
- done();
- })
- );
-
- utilsTest(
- 'full url: single line request data',
- 'POST https://somehost/_search',
- singleLineRequest.data,
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'POST',
- url: 'https://somehost/_search',
- data: [singleLineRequest.data],
- };
- compareRequest(request, expected);
- done();
- })
- );
-
- utilsTest(
- 'request with no data followed by a new line',
- getRequestNoData.prefix,
- '\n',
- callWithEditorMethod('getRequestRange', (range, done) => {
- compareRequest(range, {
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 1, column: 11 },
- });
- done();
- })
- );
-
- utilsTest(
- 'request with no data followed by a new line (data)',
- getRequestNoData.prefix,
- '\n',
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'GET',
- url: '_stats',
- data: [],
- };
- compareRequest(request, expected);
- done();
- })
- );
-
- utilsTest(
- 'request with no data',
- getRequestNoData.prefix,
- getRequestNoData.data,
- callWithEditorMethod('getRequestRange', (range, done) => {
- expect(range).toEqual({
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 1, column: 11 },
- });
- done();
- })
- );
-
- utilsTest(
- 'request with no data (data)',
- getRequestNoData.prefix,
- getRequestNoData.data,
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'GET',
- url: '_stats',
- data: [],
- };
- compareRequest(request, expected);
- done();
- })
- );
-
- utilsTest(
- 'multi doc request range',
- multiDocRequest.prefix,
- multiDocRequest.data,
- callWithEditorMethod('getRequestRange', (range, done) => {
- expect(range).toEqual({
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 3, column: 15 },
- });
- done();
- })
- );
-
- utilsTest(
- 'multi doc request data',
- multiDocRequest.prefix,
- multiDocRequest.data,
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'POST',
- url: '_bulk',
- data: multiDocRequest.data_as_array,
- };
- compareRequest(request, expected);
- done();
- })
- );
-
- const scriptRequest = {
- prefix: 'POST _search',
- data: ['{', ' "query": { "script": """', ' some script ', ' """}', '}'].join('\n'),
- };
-
- utilsTest(
- 'script request range',
- scriptRequest.prefix,
- scriptRequest.data,
- callWithEditorMethod('getRequestRange', (range, done) => {
- compareRequest(range, {
- start: { lineNumber: 1, column: 1 },
- end: { lineNumber: 6, column: 2 },
- });
- done();
- })
- );
-
- utilsTest(
- 'simple request data',
- simpleRequest.prefix,
- simpleRequest.data,
- callWithEditorMethod('getRequest', (request, done) => {
- const expected = {
- method: 'POST',
- url: '_search',
- data: [collapseLiteralStrings(simpleRequest.data)],
- };
-
- compareRequest(request, expected);
- done();
- })
- );
-
- function multiReqTest(name, editorInput, range, expected) {
- utilsTest('multi request select - ' + name, editorInput, async function (done) {
- const requests = await input.getRequestsInRange(range, false);
- // convert to format returned by request.
- _.each(expected, function (req) {
- req.data = req.data == null ? [] : [JSON.stringify(req.data, null, 2)];
- });
-
- compareRequest(requests, expected);
- done();
- });
- }
-
- multiReqTest(
- 'mid body to mid body',
- editorInput1,
- { start: { lineNumber: 13 }, end: { lineNumber: 18 } },
- [
- {
- method: 'PUT',
- url: 'index_1/type1/1',
- data: {
- f: 1,
- },
- },
- {
- method: 'PUT',
- url: 'index_1/type1/2',
- data: {
- f: 2,
- },
- },
- ]
- );
-
- multiReqTest(
- 'single request start to end',
- editorInput1,
- { start: { lineNumber: 11 }, end: { lineNumber: 14 } },
- [
- {
- method: 'PUT',
- url: 'index_1/type1/1',
- data: {
- f: 1,
- },
- },
- ]
- );
-
- multiReqTest(
- 'start to end, with comment',
- editorInput1,
- { start: { lineNumber: 7 }, end: { lineNumber: 14 } },
- [
- {
- method: 'GET',
- url: '_stats?level=shards',
- data: null,
- },
- {
- method: 'PUT',
- url: 'index_1/type1/1',
- data: {
- f: 1,
- },
- },
- ]
- );
-
- multiReqTest(
- 'before start to after end, with comments',
- editorInput1,
- { start: { lineNumber: 5 }, end: { lineNumber: 15 } },
- [
- {
- method: 'GET',
- url: '_stats?level=shards',
- data: null,
- },
- {
- method: 'PUT',
- url: 'index_1/type1/1',
- data: {
- f: 1,
- },
- },
- ]
- );
-
- multiReqTest(
- 'between requests',
- editorInput1,
- { start: { lineNumber: 22 }, end: { lineNumber: 23 } },
- []
- );
-
- multiReqTest(
- 'between requests - with comment',
- editorInput1,
- { start: { lineNumber: 21 }, end: { lineNumber: 23 } },
- []
- );
-
- multiReqTest(
- 'between requests - before comment',
- editorInput1,
- { start: { lineNumber: 20 }, end: { lineNumber: 23 } },
- []
- );
-
- function multiReqCopyAsCurlTest(name, editorInput, range, expected) {
- utilsTest('multi request copy as curl - ' + name, editorInput, async function (done) {
- const curl = await input.getRequestsAsCURL('http://localhost:9200', range);
- expect(curl).toEqual(expected);
- done();
- });
- }
-
- multiReqCopyAsCurlTest(
- 'start to end, with comment',
- editorInput1,
- { start: { lineNumber: 7 }, end: { lineNumber: 14 } },
- `
-curl -XGET "http://localhost:9200/_stats?level=shards" -H "kbn-xsrf: reporting"
-
-#in between comment
-
-curl -XPUT "http://localhost:9200/index_1/type1/1" -H "kbn-xsrf: reporting" -H "Content-Type: application/json" -d'
-{
- "f": 1
-}'`.trim()
- );
-
- multiReqCopyAsCurlTest(
- 'with single quotes',
- editorInput1,
- { start: { lineNumber: 29 }, end: { lineNumber: 33 } },
- `
-curl -XPOST "http://localhost:9200/_sql?format=txt" -H "kbn-xsrf: reporting" -H "Content-Type: application/json" -d'
-{
- "query": "SELECT prenom FROM claude_index WHERE prenom = '\\''claude'\\'' ",
- "fetch_size": 1
-}'`.trim()
- );
-
- multiReqCopyAsCurlTest(
- 'with date math index',
- editorInput1,
- { start: { lineNumber: 35 }, end: { lineNumber: 35 } },
- `
- curl -XGET "http://localhost:9200/%3Cindex_1-%7Bnow%2Fd-2d%7D%3E%2C%3Cindex_1-%7Bnow%2Fd-1d%7D%3E%2C%3Cindex_1-%7Bnow%2Fd%7D%3E%2F_search?pretty" -H "kbn-xsrf: reporting"`.trim()
- );
-
- multiReqCopyAsCurlTest(
- 'with Kibana API request',
- editorInput1,
- { start: { lineNumber: 37 }, end: { lineNumber: 37 } },
- `
-curl -XGET "http://localhost:5620/api/spaces/space" -H \"kbn-xsrf: reporting\"`.trim()
- );
-
- describe('getRequestsAsCURL', () => {
- it('should return empty string if no requests', async () => {
- input?.getCoreEditor().setValue('', false);
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 1 },
- });
- expect(curl).toEqual('');
- });
-
- it('should replace variables in the URL', async () => {
- storage.set('variables', [{ name: 'exampleVariableA', value: 'valueA' }]);
- input?.getCoreEditor().setValue('GET ${exampleVariableA}', false);
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 1 },
- });
- expect(curl).toContain('valueA');
- });
-
- it('should replace variables in the body', async () => {
- storage.set('variables', [{ name: 'exampleVariableB', value: 'valueB' }]);
- console.log(storage.get('variables'));
- input
- ?.getCoreEditor()
- .setValue('GET _search\n{\t\t"query": {\n\t\t\t"${exampleVariableB}": ""\n\t}\n}', false);
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 6 },
- });
- expect(curl).toContain('valueB');
- });
-
- it('should strip comments in the URL', async () => {
- input?.getCoreEditor().setValue('GET _search // comment', false);
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 6 },
- });
- expect(curl).not.toContain('comment');
- });
-
- it('should strip comments in the body', async () => {
- input
- ?.getCoreEditor()
- .setValue('{\n\t"query": {\n\t\t"match_all": {} // comment \n\t}\n}', false);
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 8 },
- });
- console.log('curl', curl);
- expect(curl).not.toContain('comment');
- });
-
- it('should strip multi-line comments in the body', async () => {
- input
- ?.getCoreEditor()
- .setValue('{\n\t"query": {\n\t\t"match_all": {} /* comment */\n\t}\n}', false);
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 8 },
- });
- console.log('curl', curl);
- expect(curl).not.toContain('comment');
- });
-
- it('should replace multiple variables in the URL', async () => {
- storage.set('variables', [
- { name: 'exampleVariableA', value: 'valueA' },
- { name: 'exampleVariableB', value: 'valueB' },
- ]);
- input?.getCoreEditor().setValue('GET ${exampleVariableA}/${exampleVariableB}', false);
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 1 },
- });
- expect(curl).toContain('valueA');
- expect(curl).toContain('valueB');
- });
-
- it('should replace multiple variables in the body', async () => {
- storage.set('variables', [
- { name: 'exampleVariableA', value: 'valueA' },
- { name: 'exampleVariableB', value: 'valueB' },
- ]);
- input
- ?.getCoreEditor()
- .setValue(
- 'GET _search\n{\t\t"query": {\n\t\t\t"${exampleVariableA}": "${exampleVariableB}"\n\t}\n}',
- false
- );
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 6 },
- });
- expect(curl).toContain('valueA');
- expect(curl).toContain('valueB');
- });
-
- it('should replace variables in bulk request', async () => {
- storage.set('variables', [
- { name: 'exampleVariableA', value: 'valueA' },
- { name: 'exampleVariableB', value: 'valueB' },
- ]);
- input
- ?.getCoreEditor()
- .setValue(
- 'POST _bulk\n{"index": {"_id": "0"}}\n{"field" : "${exampleVariableA}"}\n{"index": {"_id": "1"}}\n{"field" : "${exampleVariableB}"}\n',
- false
- );
- const curl = await input.getRequestsAsCURL('http://localhost:9200', {
- start: { lineNumber: 1 },
- end: { lineNumber: 4 },
- });
- expect(curl).toContain('valueA');
- expect(curl).toContain('valueB');
- });
- });
-});
diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.mocks.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.mocks.ts
deleted file mode 100644
index f0ec279fb4ffe..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.mocks.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-/* eslint no-undef: 0 */
-
-import '../legacy_core_editor/legacy_core_editor.test.mocks';
-
-import jQuery from 'jquery';
-jest.spyOn(jQuery, 'ajax').mockImplementation(
- () =>
- new Promise(() => {
- // never resolve
- }) as any
-);
diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts
deleted file mode 100644
index f6b0439cb283e..0000000000000
--- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import _ from 'lodash';
-import { parse } from 'hjson';
-import { XJson } from '@kbn/es-ui-shared-plugin/public';
-
-import RowParser from '../../../lib/row_parser';
-import * as utils from '../../../lib/utils';
-import { constructUrl } from '../../../lib/es/es';
-
-import { CoreEditor, Position, Range } from '../../../types';
-import { createTokenIterator } from '../../factories';
-import createAutocompleter from '../../../lib/autocomplete/autocomplete';
-import { getStorage, StorageKeys } from '../../../services';
-import { DEFAULT_VARIABLES } from '../../../../common/constants';
-
-const { collapseLiteralStrings } = XJson;
-
-export class SenseEditor {
- currentReqRange: (Range & { markerRef: unknown }) | null;
- parser: RowParser;
-
- private readonly autocomplete: ReturnType;
-
- constructor(private readonly coreEditor: CoreEditor) {
- this.currentReqRange = null;
- this.parser = new RowParser(this.coreEditor);
- this.autocomplete = createAutocompleter({
- coreEditor,
- parser: this.parser,
- });
- this.coreEditor.registerAutocompleter(this.autocomplete.getCompletions);
- this.coreEditor.on(
- 'tokenizerUpdate',
- this.highlightCurrentRequestsAndUpdateActionBar.bind(this)
- );
- this.coreEditor.on('changeCursor', this.highlightCurrentRequestsAndUpdateActionBar.bind(this));
- this.coreEditor.on('changeScrollTop', this.updateActionsBar.bind(this));
- }
-
- prevRequestStart = (rowOrPos?: number | Position): Position => {
- let curRow: number;
-
- if (rowOrPos == null) {
- curRow = this.coreEditor.getCurrentPosition().lineNumber;
- } else if (_.isObject(rowOrPos)) {
- curRow = (rowOrPos as Position).lineNumber;
- } else {
- curRow = rowOrPos as number;
- }
-
- while (curRow > 0 && !this.parser.isStartRequestRow(curRow, this.coreEditor)) curRow--;
-
- return {
- lineNumber: curRow,
- column: 1,
- };
- };
-
- nextRequestStart = (rowOrPos?: number | Position) => {
- let curRow: number;
- if (rowOrPos == null) {
- curRow = this.coreEditor.getCurrentPosition().lineNumber;
- } else if (_.isObject(rowOrPos)) {
- curRow = (rowOrPos as Position).lineNumber;
- } else {
- curRow = rowOrPos as number;
- }
- const maxLines = this.coreEditor.getLineCount();
- for (; curRow < maxLines - 1; curRow++) {
- if (this.parser.isStartRequestRow(curRow, this.coreEditor)) {
- break;
- }
- }
- return {
- row: curRow,
- column: 0,
- };
- };
-
- autoIndent = _.debounce(async () => {
- await this.coreEditor.waitForLatestTokens();
- const reqRange = await this.getRequestRange();
- if (!reqRange) {
- return;
- }
- const parsedReq = await this.getRequest();
-
- if (!parsedReq) {
- return;
- }
-
- if (parsedReq.data.some((doc) => utils.hasComments(doc))) {
- /**
- * Comments require different approach for indentation and do not have condensed format
- * We need to delegate indentation logic to coreEditor since it has access to session and other methods used for formatting and indenting the comments
- */
- this.coreEditor.autoIndent(parsedReq.range);
- return;
- }
-
- if (parsedReq.data && parsedReq.data.length > 0) {
- let indent = parsedReq.data.length === 1; // unindent multi docs by default
- let formattedData = utils.formatRequestBodyDoc(parsedReq.data, indent);
- if (!formattedData.changed) {
- // toggle.
- indent = !indent;
- formattedData = utils.formatRequestBodyDoc(parsedReq.data, indent);
- }
- parsedReq.data = formattedData.data;
-
- this.replaceRequestRange(parsedReq, reqRange);
- }
- }, 25);
-
- update = async (data: string, reTokenizeAll = false) => {
- return this.coreEditor.setValue(data, reTokenizeAll);
- };
-
- replaceRequestRange = (
- newRequest: { method: string; url: string; data: string | string[] },
- requestRange: Range
- ) => {
- const text = utils.textFromRequest(newRequest);
- if (requestRange) {
- this.coreEditor.replaceRange(requestRange, text);
- } else {
- // just insert where we are
- this.coreEditor.insert(this.coreEditor.getCurrentPosition(), text);
- }
- };
-
- getRequestRange = async (lineNumber?: number): Promise => {
- await this.coreEditor.waitForLatestTokens();
-
- if (this.parser.isInBetweenRequestsRow(lineNumber)) {
- return null;
- }
-
- const reqStart = this.prevRequestStart(lineNumber);
- const reqEnd = this.nextRequestEnd(reqStart);
-
- return {
- start: {
- ...reqStart,
- },
- end: {
- ...reqEnd,
- },
- };
- };
-
- expandRangeToRequestEdges = async (
- range = this.coreEditor.getSelectionRange()
- ): Promise => {
- await this.coreEditor.waitForLatestTokens();
-
- let startLineNumber = range.start.lineNumber;
- let endLineNumber = range.end.lineNumber;
- const maxLine = Math.max(1, this.coreEditor.getLineCount());
-
- if (this.parser.isInBetweenRequestsRow(startLineNumber)) {
- /* Do nothing... */
- } else {
- for (; startLineNumber >= 1; startLineNumber--) {
- if (this.parser.isStartRequestRow(startLineNumber)) {
- break;
- }
- }
- }
-
- if (startLineNumber < 1 || startLineNumber > endLineNumber) {
- return null;
- }
- // move end row to the previous request end if between requests, otherwise walk forward
- if (this.parser.isInBetweenRequestsRow(endLineNumber)) {
- for (; endLineNumber >= startLineNumber; endLineNumber--) {
- if (this.parser.isEndRequestRow(endLineNumber)) {
- break;
- }
- }
- } else {
- for (; endLineNumber <= maxLine; endLineNumber++) {
- if (this.parser.isEndRequestRow(endLineNumber)) {
- break;
- }
- }
- }
-
- if (endLineNumber < startLineNumber || endLineNumber > maxLine) {
- return null;
- }
-
- const endColumn =
- (this.coreEditor.getLineValue(endLineNumber) || '').replace(/\s+$/, '').length + 1;
- return {
- start: {
- lineNumber: startLineNumber,
- column: 1,
- },
- end: {
- lineNumber: endLineNumber,
- column: endColumn,
- },
- };
- };
-
- getRequestInRange = async (range?: Range) => {
- await this.coreEditor.waitForLatestTokens();
- if (!range) {
- return null;
- }
- const request: {
- method: string;
- data: string[];
- url: string;
- range: Range;
- } = {
- method: '',
- data: [],
- url: '',
- range,
- };
-
- const pos = range.start;
- const tokenIter = createTokenIterator({ editor: this.coreEditor, position: pos });
- let t = tokenIter.getCurrentToken();
- if (this.parser.isEmptyToken(t)) {
- // if the row starts with some spaces, skip them.
- t = this.parser.nextNonEmptyToken(tokenIter);
- }
- if (t == null) {
- return null;
- }
-
- request.method = t.value;
- t = this.parser.nextNonEmptyToken(tokenIter);
-
- if (!t || t.type === 'method') {
- return null;
- }
-
- request.url = '';
-
- while (t && t.type && (t.type.indexOf('url') === 0 || t.type === 'variable.template')) {
- request.url += t.value;
- t = tokenIter.stepForward();
- }
- if (this.parser.isEmptyToken(t)) {
- // if the url row ends with some spaces, skip them.
- t = this.parser.nextNonEmptyToken(tokenIter);
- }
-
- // If the url row ends with a comment, skip it
- while (this.parser.isCommentToken(t)) {
- t = tokenIter.stepForward();
- }
-
- let bodyStartLineNumber = (t ? 0 : 1) + tokenIter.getCurrentPosition().lineNumber; // artificially increase end of docs.
- let dataEndPos: Position;
- while (
- bodyStartLineNumber < range.end.lineNumber ||
- (bodyStartLineNumber === range.end.lineNumber && 1 < range.end.column)
- ) {
- dataEndPos = this.nextDataDocEnd({
- lineNumber: bodyStartLineNumber,
- column: 1,
- });
- const bodyRange: Range = {
- start: {
- lineNumber: bodyStartLineNumber,
- column: 1,
- },
- end: dataEndPos,
- };
- const data = this.coreEditor.getValueInRange(bodyRange)!;
- request.data.push(data.trim());
- bodyStartLineNumber = dataEndPos.lineNumber + 1;
- }
-
- return request;
- };
-
- getRequestsInRange = async (
- range = this.coreEditor.getSelectionRange(),
- includeNonRequestBlocks = false
- ): Promise => {
- await this.coreEditor.waitForLatestTokens();
- if (!range) {
- return [];
- }
-
- const expandedRange = await this.expandRangeToRequestEdges(range);
- if (!expandedRange) {
- return [];
- }
-
- const requests: unknown[] = [];
-
- let rangeStartCursor = expandedRange.start.lineNumber;
- const endLineNumber = expandedRange.end.lineNumber;
-
- // move to the next request start (during the second iterations this may not be exactly on a request
- let currentLineNumber = expandedRange.start.lineNumber;
-
- const flushNonRequestBlock = () => {
- if (includeNonRequestBlocks) {
- const nonRequestPrefixBlock = this.coreEditor
- .getLines(rangeStartCursor, currentLineNumber - 1)
- .join('\n');
- if (nonRequestPrefixBlock) {
- requests.push(nonRequestPrefixBlock);
- }
- }
- };
-
- while (currentLineNumber <= endLineNumber) {
- if (this.parser.isStartRequestRow(currentLineNumber)) {
- flushNonRequestBlock();
- const request = await this.getRequest(currentLineNumber);
- if (!request) {
- // Something has probably gone wrong.
- return requests;
- } else {
- requests.push(request);
- rangeStartCursor = currentLineNumber = request.range.end.lineNumber + 1;
- }
- } else {
- ++currentLineNumber;
- }
- }
-
- flushNonRequestBlock();
-
- return requests;
- };
-
- getRequest = async (row?: number) => {
- await this.coreEditor.waitForLatestTokens();
- if (this.parser.isInBetweenRequestsRow(row)) {
- return null;
- }
-
- const range = await this.getRequestRange(row);
- return this.getRequestInRange(range!);
- };
-
- moveToPreviousRequestEdge = async () => {
- await this.coreEditor.waitForLatestTokens();
- const pos = this.coreEditor.getCurrentPosition();
- for (
- pos.lineNumber--;
- pos.lineNumber > 1 && !this.parser.isRequestEdge(pos.lineNumber);
- pos.lineNumber--
- ) {
- // loop for side effects
- }
- this.coreEditor.moveCursorToPosition({
- lineNumber: pos.lineNumber,
- column: 1,
- });
- };
-
- moveToNextRequestEdge = async (moveOnlyIfNotOnEdge: boolean) => {
- await this.coreEditor.waitForLatestTokens();
- const pos = this.coreEditor.getCurrentPosition();
- const maxRow = this.coreEditor.getLineCount();
- if (!moveOnlyIfNotOnEdge) {
- pos.lineNumber++;
- }
- for (
- ;
- pos.lineNumber < maxRow && !this.parser.isRequestEdge(pos.lineNumber);
- pos.lineNumber++
- ) {
- // loop for side effects
- }
- this.coreEditor.moveCursorToPosition({
- lineNumber: pos.lineNumber,
- column: 1,
- });
- };
-
- nextRequestEnd = (pos: Position): Position => {
- pos = pos || this.coreEditor.getCurrentPosition();
- const maxLines = this.coreEditor.getLineCount();
- let curLineNumber = pos.lineNumber;
- for (; curLineNumber <= maxLines; ++curLineNumber) {
- const curRowMode = this.parser.getRowParseMode(curLineNumber);
- // eslint-disable-next-line no-bitwise
- if ((curRowMode & this.parser.MODE.REQUEST_END) > 0) {
- break;
- }
- // eslint-disable-next-line no-bitwise
- if (curLineNumber !== pos.lineNumber && (curRowMode & this.parser.MODE.REQUEST_START) > 0) {
- break;
- }
- }
-
- const column =
- (this.coreEditor.getLineValue(curLineNumber) || '').replace(/\s+$/, '').length + 1;
-
- return {
- lineNumber: curLineNumber,
- column,
- };
- };
-
- nextDataDocEnd = (pos: Position): Position => {
- pos = pos || this.coreEditor.getCurrentPosition();
- let curLineNumber = pos.lineNumber;
- const maxLines = this.coreEditor.getLineCount();
- for (; curLineNumber < maxLines; curLineNumber++) {
- const curRowMode = this.parser.getRowParseMode(curLineNumber);
- // eslint-disable-next-line no-bitwise
- if ((curRowMode & this.parser.MODE.REQUEST_END) > 0) {
- break;
- }
- // eslint-disable-next-line no-bitwise
- if ((curRowMode & this.parser.MODE.MULTI_DOC_CUR_DOC_END) > 0) {
- break;
- }
- // eslint-disable-next-line no-bitwise
- if (curLineNumber !== pos.lineNumber && (curRowMode & this.parser.MODE.REQUEST_START) > 0) {
- break;
- }
- }
-
- const column =
- (this.coreEditor.getLineValue(curLineNumber) || '').length +
- 1; /* Range goes to 1 after last char */
-
- return {
- lineNumber: curLineNumber,
- column,
- };
- };
-
- highlightCurrentRequestsAndUpdateActionBar = _.debounce(async () => {
- await this.coreEditor.waitForLatestTokens();
- const expandedRange = await this.expandRangeToRequestEdges();
- if (expandedRange === null && this.currentReqRange === null) {
- return;
- }
- if (
- expandedRange !== null &&
- this.currentReqRange !== null &&
- expandedRange.start.lineNumber === this.currentReqRange.start.lineNumber &&
- expandedRange.end.lineNumber === this.currentReqRange.end.lineNumber
- ) {
- // same request, now see if we are on the first line and update the action bar
- const cursorLineNumber = this.coreEditor.getCurrentPosition().lineNumber;
- if (cursorLineNumber === this.currentReqRange.start.lineNumber) {
- this.updateActionsBar();
- }
- return; // nothing to do..
- }
-
- if (this.currentReqRange) {
- this.coreEditor.removeMarker(this.currentReqRange.markerRef);
- }
-
- this.currentReqRange = expandedRange as any;
- if (this.currentReqRange) {
- this.currentReqRange.markerRef = this.coreEditor.addMarker(this.currentReqRange);
- }
- this.updateActionsBar();
- }, 25);
-
- getRequestsAsCURL = async (elasticsearchBaseUrl: string, range?: Range): Promise => {
- const variables = getStorage().get(StorageKeys.VARIABLES, DEFAULT_VARIABLES);
- let requests = await this.getRequestsInRange(range, true);
- requests = utils.replaceVariables(requests, variables);
- const result = _.map(requests, (req) => {
- if (typeof req === 'string') {
- // no request block
- return req;
- }
-
- const path = req.url;
- const method = req.method;
- const data = req.data;
-
- // this is the first url defined in elasticsearch.hosts
- const url = constructUrl(elasticsearchBaseUrl, path);
-
- // Append 'kbn-xsrf' header to bypass (XSRF/CSRF) protections
- let ret = `curl -X${method.toUpperCase()} "${url}" -H "kbn-xsrf: reporting"`;
-
- if (data && data.length) {
- const joinedData = data.join('\n');
- let dataAsString: string;
-
- try {
- ret += ` -H "Content-Type: application/json" -d'\n`;
-
- if (utils.hasComments(joinedData)) {
- // if there are comments in the data, we need to strip them out
- const dataWithoutComments = parse(joinedData);
- dataAsString = collapseLiteralStrings(JSON.stringify(dataWithoutComments, null, 2));
- } else {
- dataAsString = collapseLiteralStrings(joinedData);
- }
- // We escape single quoted strings that are wrapped in single quoted strings
- ret += dataAsString.replace(/'/g, "'\\''");
- if (data.length > 1) {
- ret += '\n';
- } // end with a new line
- ret += "'";
- } catch (e) {
- throw new Error(`Error parsing data: ${e.message}`);
- }
- }
- return ret;
- });
-
- return result.join('\n');
- };
-
- updateActionsBar = () => {
- return this.coreEditor.legacyUpdateUI(this.currentReqRange);
- };
-
- getCoreEditor() {
- return this.coreEditor;
- }
-}
diff --git a/src/plugins/console/public/application/stores/editor.ts b/src/plugins/console/public/application/stores/editor.ts
index 556f4f64337e6..8ae24e5a422b7 100644
--- a/src/plugins/console/public/application/stores/editor.ts
+++ b/src/plugins/console/public/application/stores/editor.ts
@@ -12,7 +12,6 @@ import { produce } from 'immer';
import { identity } from 'fp-ts/lib/function';
import { DevToolsSettings, DEFAULT_SETTINGS } from '../../services';
import { TextObject } from '../../../common/text_object';
-import { SenseEditor } from '../models';
import { SHELL_TAB_ID } from '../containers/main/constants';
import { MonacoEditorActionsProvider } from '../containers/editor/monaco_editor_actions_provider';
import { RequestToRestore } from '../../types';
@@ -39,7 +38,7 @@ export const initialValue: Store = produce(
);
export type Action =
- | { type: 'setInputEditor'; payload: SenseEditor | MonacoEditorActionsProvider }
+ | { type: 'setInputEditor'; payload: MonacoEditorActionsProvider }
| { type: 'setCurrentTextObject'; payload: TextObject }
| { type: 'updateSettings'; payload: DevToolsSettings }
| { type: 'setCurrentView'; payload: string }
diff --git a/src/plugins/console/public/lib/ace_token_provider/index.ts b/src/plugins/console/public/lib/ace_token_provider/index.ts
deleted file mode 100644
index 8819ac19a1262..0000000000000
--- a/src/plugins/console/public/lib/ace_token_provider/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-export * from './token_provider';
diff --git a/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts b/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts
deleted file mode 100644
index b36d9855414bd..0000000000000
--- a/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import '../../application/models/sense_editor/sense_editor.test.mocks';
-
-import $ from 'jquery';
-
-// TODO:
-// We import from application models as a convenient way to bootstrap loading up of an editor using
-// this lib. We also need to import application specific mocks which is not ideal.
-// In this situation, the token provider lib knows about app models in tests, which it really shouldn't. Should create
-// a better sandbox in future.
-import { create, SenseEditor } from '../../application/models/sense_editor';
-
-import { Position, Token, TokensProvider } from '../../types';
-
-interface RunTestArgs {
- input: string;
- done?: () => void;
-}
-
-describe('Ace (legacy) token provider', () => {
- let senseEditor: SenseEditor;
- let tokenProvider: TokensProvider;
- beforeEach(() => {
- // Set up our document body
- document.body.innerHTML = ``;
-
- senseEditor = create(document.querySelector('#ConAppEditor')!);
-
- $(senseEditor.getCoreEditor().getContainer())!.show();
-
- (senseEditor as any).autocomplete._test.removeChangeListener();
- tokenProvider = senseEditor.getCoreEditor().getTokenProvider();
- });
-
- afterEach(async () => {
- $(senseEditor.getCoreEditor().getContainer())!.hide();
- (senseEditor as any).autocomplete._test.addChangeListener();
- await senseEditor.update('', true);
- });
-
- describe('#getTokens', () => {
- const runTest = ({
- input,
- expectedTokens,
- done,
- lineNumber = 1,
- }: RunTestArgs & { expectedTokens: Token[] | null; lineNumber?: number }) => {
- senseEditor.update(input, true).then(() => {
- const tokens = tokenProvider.getTokens(lineNumber);
- expect(tokens).toEqual(expectedTokens);
- if (done) done();
- });
- };
-
- describe('base cases', () => {
- test('case 1 - only url', (done) => {
- runTest({
- input: `GET http://somehost/_search`,
- expectedTokens: [
- { type: 'method', value: 'GET', position: { lineNumber: 1, column: 1 } },
- { type: 'whitespace', value: ' ', position: { lineNumber: 1, column: 4 } },
- {
- type: 'url.protocol_host',
- value: 'http://somehost',
- position: { lineNumber: 1, column: 5 },
- },
- { type: 'url.slash', value: '/', position: { lineNumber: 1, column: 20 } },
- { type: 'url.part', value: '_search', position: { lineNumber: 1, column: 21 } },
- ],
- done,
- });
- });
-
- test('case 2 - basic auth in host name', (done) => {
- runTest({
- input: `GET http://test:user@somehost/`,
- expectedTokens: [
- { type: 'method', value: 'GET', position: { lineNumber: 1, column: 1 } },
- { type: 'whitespace', value: ' ', position: { lineNumber: 1, column: 4 } },
- {
- type: 'url.protocol_host',
- value: 'http://test:user@somehost',
- position: { lineNumber: 1, column: 5 },
- },
- { type: 'url.slash', value: '/', position: { lineNumber: 1, column: 30 } },
- ],
- done,
- });
- });
-
- test('case 3 - handles empty lines', (done) => {
- runTest({
- input: `POST abc
-
-
-{
-`,
- expectedTokens: [
- { type: 'method', value: 'POST', position: { lineNumber: 1, column: 1 } },
- { type: 'whitespace', value: ' ', position: { lineNumber: 1, column: 5 } },
- { type: 'url.part', value: 'abc', position: { lineNumber: 1, column: 6 } },
- ],
- done,
- lineNumber: 1,
- });
- });
- });
-
- describe('with newlines', () => {
- test('case 1 - newlines base case', (done) => {
- runTest({
- input: `GET http://test:user@somehost/
-{
- "wudup": "!"
-}`,
- expectedTokens: [
- { type: 'whitespace', value: ' ', position: { lineNumber: 3, column: 1 } },
- { type: 'variable', value: '"wudup"', position: { lineNumber: 3, column: 3 } },
- { type: 'punctuation.colon', value: ':', position: { lineNumber: 3, column: 10 } },
- { type: 'whitespace', value: ' ', position: { lineNumber: 3, column: 11 } },
- { type: 'string', value: '"!"', position: { lineNumber: 3, column: 12 } },
- ],
- done,
- lineNumber: 3,
- });
- });
- });
-
- describe('edge cases', () => {
- test('case 1 - getting token outside of document', (done) => {
- runTest({
- input: `GET http://test:user@somehost/
-{
- "wudup": "!"
-}`,
- expectedTokens: null,
- done,
- lineNumber: 100,
- });
- });
-
- test('case 2 - empty lines', (done) => {
- runTest({
- input: `GET http://test:user@somehost/
-
-
-
-
-{
- "wudup": "!"
-}`,
- expectedTokens: [],
- done,
- lineNumber: 5,
- });
- });
- });
- });
-
- describe('#getTokenAt', () => {
- const runTest = ({
- input,
- expectedToken,
- done,
- position,
- }: RunTestArgs & { expectedToken: Token | null; position: Position }) => {
- senseEditor.update(input, true).then(() => {
- const tokens = tokenProvider.getTokenAt(position);
- expect(tokens).toEqual(expectedToken);
- if (done) done();
- });
- };
-
- describe('base cases', () => {
- it('case 1 - gets a token from the url', (done) => {
- const input = `GET http://test:user@somehost/`;
- runTest({
- input,
- expectedToken: {
- position: { lineNumber: 1, column: 4 },
- type: 'whitespace',
- value: ' ',
- },
- position: { lineNumber: 1, column: 5 },
- });
-
- runTest({
- input,
- expectedToken: {
- position: { lineNumber: 1, column: 5 },
- type: 'url.protocol_host',
- value: 'http://test:user@somehost',
- },
- position: { lineNumber: 1, column: input.length },
- done,
- });
- });
- });
-
- describe('special cases', () => {
- it('case 1 - handles input outside of range', (done) => {
- runTest({
- input: `GET abc`,
- expectedToken: null,
- done,
- position: { lineNumber: 1, column: 99 },
- });
- });
- });
- });
-});
diff --git a/src/plugins/console/public/lib/ace_token_provider/token_provider.ts b/src/plugins/console/public/lib/ace_token_provider/token_provider.ts
deleted file mode 100644
index 9e61771946771..0000000000000
--- a/src/plugins/console/public/lib/ace_token_provider/token_provider.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { IEditSession, TokenInfo as BraceTokenInfo } from 'brace';
-import { TokensProvider, Token, Position } from '../../types';
-
-// Brace's token information types are not accurate.
-interface TokenInfo extends BraceTokenInfo {
- type: string;
-}
-
-const toToken = (lineNumber: number, column: number, token: TokenInfo): Token => ({
- type: token.type,
- value: token.value,
- position: {
- lineNumber,
- column,
- },
-});
-
-const toTokens = (lineNumber: number, tokens: TokenInfo[]): Token[] => {
- let acc = '';
- return tokens.map((token) => {
- const column = acc.length + 1;
- acc += token.value;
- return toToken(lineNumber, column, token);
- });
-};
-
-const extractTokenFromAceTokenRow = (
- lineNumber: number,
- column: number,
- aceTokens: TokenInfo[]
-) => {
- let acc = '';
- for (const token of aceTokens) {
- const start = acc.length + 1;
- acc += token.value;
- const end = acc.length;
- if (column < start) continue;
- if (column > end + 1) continue;
- return toToken(lineNumber, start, token);
- }
- return null;
-};
-
-export class AceTokensProvider implements TokensProvider {
- constructor(private readonly session: IEditSession) {}
-
- getTokens(lineNumber: number): Token[] | null {
- if (lineNumber < 1) return null;
-
- // Important: must use a .session.getLength because this is a cached value.
- // Calculating line length here will lead to performance issues because this function
- // may be called inside of tight loops.
- const lineCount = this.session.getLength();
- if (lineNumber > lineCount) {
- return null;
- }
-
- const tokens = this.session.getTokens(lineNumber - 1) as unknown as TokenInfo[];
- if (!tokens || !tokens.length) {
- // We are inside of the document but have no tokens for this line. Return an empty
- // array to represent this empty line.
- return [];
- }
-
- return toTokens(lineNumber, tokens);
- }
-
- getTokenAt(pos: Position): Token | null {
- const tokens = this.session.getTokens(pos.lineNumber - 1) as unknown as TokenInfo[];
- if (tokens) {
- return extractTokenFromAceTokenRow(pos.lineNumber, pos.column, tokens);
- }
- return null;
- }
-}
diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts
deleted file mode 100644
index 73ef1981cfc0b..0000000000000
--- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts
+++ /dev/null
@@ -1,1316 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import _ from 'lodash';
-import { i18n } from '@kbn/i18n';
-
-// TODO: All of these imports need to be moved to the core editor so that it can inject components from there.
-import {
- getEndpointBodyCompleteComponents,
- getGlobalAutocompleteComponents,
- getTopLevelUrlCompleteComponents,
- getUnmatchedEndpointComponents,
-} from '../kb/kb';
-
-import { createTokenIterator } from '../../application/factories';
-import type { CoreEditor, Position, Range, Token } from '../../types';
-import type RowParser from '../row_parser';
-
-import * as utils from '../utils';
-
-import { populateContext } from './engine';
-import type { AutoCompleteContext, DataAutoCompleteRulesOneOf, ResultTerm } from './types';
-import { URL_PATH_END_MARKER, ConstantComponent } from './components';
-import { looksLikeTypingIn } from './looks_like_typing_in';
-
-let lastEvaluatedToken: Token | null = null;
-
-function isUrlParamsToken(token: { type: string } | null) {
- switch ((token || {}).type) {
- case 'url.param':
- case 'url.equal':
- case 'url.value':
- case 'url.questionmark':
- case 'url.amp':
- return true;
- default:
- return false;
- }
-}
-
-/* Logs the provided arguments to the console if the `window.autocomplete_trace` flag is set to true.
- * This function checks if the `autocomplete_trace` flag is enabled on the `window` object. This is
- * only used when executing functional tests.
- * If the flag is enabled, it logs each argument to the console.
- * If an argument is an object, it is stringified before logging.
- */
-const tracer = (...args: any[]) => {
- // @ts-ignore
- if (window.autocomplete_trace) {
- // eslint-disable-next-line no-console
- console.log.call(
- console,
- ..._.map(args, (arg) => {
- return typeof arg === 'object' ? JSON.stringify(arg) : arg;
- })
- );
- }
-};
-
-/**
- * Get the method and token paths for a specific position in the current editor buffer.
- *
- * This function can be used for getting autocomplete information or for getting more information
- * about the endpoint associated with autocomplete. In future, these concerns should be better
- * separated.
- *
- */
-export function getCurrentMethodAndTokenPaths(
- editor: CoreEditor,
- pos: Position,
- parser: RowParser,
- forceEndOfUrl?: boolean /* Flag for indicating whether we want to avoid early escape optimization. */
-) {
- const tokenIter = createTokenIterator({
- editor,
- position: pos,
- });
- const startPos = pos;
- let bodyTokenPath: string[] | null = [];
- const ret: AutoCompleteContext = {};
-
- const STATES = {
- looking_for_key: 0, // looking for a key but without jumping over anything but white space and colon.
- looking_for_scope_start: 1, // skip everything until scope start
- start: 3,
- };
- let state = STATES.start;
-
- // initialization problems -
- let t = tokenIter.getCurrentToken();
- if (t) {
- if (startPos.column === 1) {
- // if we are at the beginning of the line, the current token is the one after cursor, not before which
- // deviates from the standard.
- t = tokenIter.stepBackward();
- state = STATES.looking_for_scope_start;
- }
- } else {
- if (startPos.column === 1) {
- // empty lines do no have tokens, move one back
- t = tokenIter.stepBackward();
- state = STATES.start;
- }
- }
-
- let walkedSomeBody = false;
-
- // climb one scope at a time and get the scope key
- for (; t && t.type.indexOf('url') === -1 && t.type !== 'method'; t = tokenIter.stepBackward()) {
- if (t.type !== 'whitespace') {
- walkedSomeBody = true;
- } // marks we saw something
-
- switch (t.type) {
- case 'variable':
- if (state === STATES.looking_for_key) {
- bodyTokenPath.unshift(t.value.trim().replace(/"/g, ''));
- }
- state = STATES.looking_for_scope_start; // skip everything until the beginning of this scope
- break;
-
- case 'paren.lparen':
- bodyTokenPath.unshift(t.value);
- if (state === STATES.looking_for_scope_start) {
- // found it. go look for the relevant key
- state = STATES.looking_for_key;
- }
- break;
- case 'paren.rparen':
- // reset he search for key
- state = STATES.looking_for_scope_start;
- // and ignore this sub scope..
- let parenCount = 1;
- t = tokenIter.stepBackward();
- while (t && parenCount > 0) {
- switch (t.type) {
- case 'paren.lparen':
- parenCount--;
- break;
- case 'paren.rparen':
- parenCount++;
- break;
- }
- if (parenCount > 0) {
- t = tokenIter.stepBackward();
- }
- }
- if (!t) {
- tracer(`paren.rparen: oops we run out.. we don't know what's up return null`);
- return {};
- }
- continue;
- case 'punctuation.end_triple_quote':
- // reset the search for key
- state = STATES.looking_for_scope_start;
- for (t = tokenIter.stepBackward(); t; t = tokenIter.stepBackward()) {
- if (t.type === 'punctuation.start_triple_quote') {
- t = tokenIter.stepBackward();
- break;
- }
- }
- if (!t) {
- tracer(`paren.rparen: oops we run out.. we don't know what's up return null`);
- return {};
- }
- continue;
- case 'punctuation.start_triple_quote':
- if (state === STATES.start) {
- state = STATES.looking_for_key;
- } else if (state === STATES.looking_for_key) {
- state = STATES.looking_for_scope_start;
- }
- bodyTokenPath.unshift('"""');
- continue;
- case 'string':
- case 'constant.numeric':
- case 'constant.language.boolean':
- case 'text':
- if (state === STATES.start) {
- state = STATES.looking_for_key;
- } else if (state === STATES.looking_for_key) {
- state = STATES.looking_for_scope_start;
- }
-
- break;
- case 'punctuation.comma':
- if (state === STATES.start) {
- state = STATES.looking_for_scope_start;
- }
- break;
- case 'punctuation.colon':
- case 'whitespace':
- if (state === STATES.start) {
- state = STATES.looking_for_key;
- }
- break; // skip white space
- }
- }
-
- if (walkedSomeBody && (!bodyTokenPath || bodyTokenPath.length === 0) && !forceEndOfUrl) {
- tracer(
- 'we had some content and still no path',
- '-> the cursor is position after a closed body',
- '-> no auto complete'
- );
- return {};
- }
-
- ret.urlTokenPath = [];
- if (tokenIter.getCurrentPosition().lineNumber === startPos.lineNumber) {
- if (t && (t.type === 'url.part' || t.type === 'url.param' || t.type === 'url.value')) {
- // we are forcing the end of the url for the purposes of determining an endpoint
- if (forceEndOfUrl && t.type === 'url.part') {
- ret.urlTokenPath.push(t.value);
- ret.urlTokenPath.push(URL_PATH_END_MARKER);
- }
- // we are on the same line as cursor and dealing with a url. Current token is not part of the context
- t = tokenIter.stepBackward();
- // This will force method parsing
- while (t!.type === 'whitespace') {
- t = tokenIter.stepBackward();
- }
- }
- bodyTokenPath = null; // no not on a body line.
- }
-
- ret.bodyTokenPath = bodyTokenPath;
-
- ret.urlParamsTokenPath = null;
- ret.requestStartRow = tokenIter.getCurrentPosition().lineNumber;
- let curUrlPart:
- | null
- | string
- | Array>
- | undefined
- | Record;
-
- while (t && isUrlParamsToken(t)) {
- switch (t.type) {
- case 'url.value':
- if (Array.isArray(curUrlPart)) {
- curUrlPart.unshift(t.value);
- } else if (curUrlPart) {
- curUrlPart = [t.value, curUrlPart];
- } else {
- curUrlPart = t.value;
- }
- break;
- case 'url.comma':
- if (!curUrlPart) {
- curUrlPart = [];
- } else if (!Array.isArray(curUrlPart)) {
- curUrlPart = [curUrlPart];
- }
- break;
- case 'url.param':
- const v = curUrlPart;
- curUrlPart = {};
- curUrlPart[t.value] = v;
- break;
- case 'url.amp':
- case 'url.questionmark':
- if (!ret.urlParamsTokenPath) {
- ret.urlParamsTokenPath = [];
- }
- ret.urlParamsTokenPath.unshift((curUrlPart as Record) || {});
- curUrlPart = null;
- break;
- }
- t = tokenIter.stepBackward();
- }
-
- curUrlPart = null;
- while (t && t.type.indexOf('url') !== -1) {
- switch (t.type) {
- case 'url.part':
- if (Array.isArray(curUrlPart)) {
- curUrlPart.unshift(t.value);
- } else if (curUrlPart) {
- curUrlPart = [t.value, curUrlPart];
- } else {
- curUrlPart = t.value;
- }
- break;
- case 'url.comma':
- if (!curUrlPart) {
- curUrlPart = [];
- } else if (!Array.isArray(curUrlPart)) {
- curUrlPart = [curUrlPart];
- }
- break;
- case 'url.slash':
- if (curUrlPart) {
- ret.urlTokenPath.unshift(curUrlPart as string);
- curUrlPart = null;
- }
- break;
- }
- t = parser.prevNonEmptyToken(tokenIter);
- }
-
- if (curUrlPart) {
- ret.urlTokenPath.unshift(curUrlPart as string);
- }
-
- if (!ret.bodyTokenPath && !ret.urlParamsTokenPath) {
- if (ret.urlTokenPath.length > 0) {
- // // started on the url, first token is current token
- ret.otherTokenValues = ret.urlTokenPath[0];
- }
- } else {
- // mark the url as completed.
- ret.urlTokenPath.push(URL_PATH_END_MARKER);
- }
-
- if (t && t.type === 'method') {
- ret.method = t.value;
- }
- return ret;
-}
-
-// eslint-disable-next-line import/no-default-export
-export default function ({
- coreEditor: editor,
- parser,
-}: {
- coreEditor: CoreEditor;
- parser: RowParser;
-}) {
- function isUrlPathToken(token: Token | null) {
- switch ((token || ({} as Token)).type) {
- case 'url.slash':
- case 'url.comma':
- case 'url.part':
- return true;
- default:
- return false;
- }
- }
-
- function addMetaToTermsList(list: ResultTerm[], meta: string, template?: string): ResultTerm[] {
- return _.map(list, function (t) {
- if (typeof t !== 'object') {
- t = { name: t };
- }
- return _.defaults(t, { meta, template });
- });
- }
-
- function replaceLinesWithPrefixPieces(prefixPieces: string[], startLineNumber: number) {
- const middlePiecesCount = prefixPieces.length - 1;
- prefixPieces.forEach((piece, index) => {
- if (index >= middlePiecesCount) {
- return;
- }
- const line = startLineNumber + index + 1;
- const column = editor.getLineValue(line).length - 1;
- const start = { lineNumber: line, column: 0 };
- const end = { lineNumber: line, column };
- editor.replace({ start, end }, piece);
- });
- }
-
- /**
- * Get a different set of templates based on the value configured in the request.
- * For example, when creating a snapshot repository of different types (`fs`, `url` etc),
- * different properties are inserted in the textarea based on the type.
- * E.g. https://github.com/elastic/kibana/blob/main/src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.create_repository.json
- */
- function getConditionalTemplate(
- name: string,
- autocompleteRules: Record | null | undefined
- ) {
- const obj = autocompleteRules && autocompleteRules[name];
-
- if (obj) {
- const currentLineNumber = editor.getCurrentPosition().lineNumber;
-
- if (hasOneOfIn(obj)) {
- // Get the line number of value that should provide different templates based on that
- const startLine = getStartLineNumber(currentLineNumber, obj.__one_of);
- // Join line values from start to current line
- const lines = editor.getLines(startLine, currentLineNumber).join('\n');
- // Get the correct template by comparing the autocomplete rules against the lines
- const prop = getProperty(lines, obj.__one_of);
- if (prop && prop.__template) {
- return prop.__template;
- }
- }
- }
- }
-
- /**
- * Check if object has a property of '__one_of'
- */
- function hasOneOfIn(value: unknown): value is { __one_of: DataAutoCompleteRulesOneOf[] } {
- return typeof value === 'object' && value !== null && '__one_of' in value;
- }
-
- /**
- * Get the start line of value that matches the autocomplete rules condition
- */
- function getStartLineNumber(currentLine: number, rules: DataAutoCompleteRulesOneOf[]): number {
- if (currentLine === 1) {
- return currentLine;
- }
- const value = editor.getLineValue(currentLine);
- const prop = getProperty(value, rules);
- if (prop) {
- return currentLine;
- }
- return getStartLineNumber(currentLine - 1, rules);
- }
-
- /**
- * Get the matching property based on the given condition
- */
- function getProperty(condition: string, rules: DataAutoCompleteRulesOneOf[]) {
- return rules.find((rule) => {
- if (rule.__condition && rule.__condition.lines_regex) {
- return new RegExp(rule.__condition.lines_regex, 'm').test(condition);
- }
- return false;
- });
- }
-
- function applyTerm(term: ResultTerm) {
- const context = term.context!;
-
- if (context?.endpoint && term.value) {
- const { data_autocomplete_rules: autocompleteRules } = context.endpoint;
- const template = getConditionalTemplate(term.value, autocompleteRules);
- if (template) {
- term.template = template;
- }
- }
- // make sure we get up to date replacement info.
- addReplacementInfoToContext(context, editor.getCurrentPosition(), term.insertValue);
-
- let termAsString;
- if (context.autoCompleteType === 'body') {
- termAsString =
- typeof term.insertValue === 'string' ? '"' + term.insertValue + '"' : term.insertValue + '';
- if (term.insertValue === '[' || term.insertValue === '{') {
- termAsString = '';
- }
- } else {
- termAsString = term.insertValue + '';
- }
-
- let valueToInsert = termAsString;
- let templateInserted = false;
- if (context.addTemplate && !_.isUndefined(term.template) && !_.isNull(term.template)) {
- let indentedTemplateLines;
- // In order to allow triple quoted strings in template completion we check the `__raw_`
- // attribute to determine whether this template should go through JSON formatting.
- if (term.template.__raw && term.template.value) {
- indentedTemplateLines = term.template.value.split('\n');
- } else {
- indentedTemplateLines = utils.jsonToString(term.template, true).split('\n');
- }
- let currentIndentation = editor.getLineValue(context.rangeToReplace!.start.lineNumber);
- currentIndentation = currentIndentation.match(/^\s*/)![0];
- for (
- let i = 1;
- i < indentedTemplateLines.length;
- i++ // skip first line
- ) {
- indentedTemplateLines[i] = currentIndentation + indentedTemplateLines[i];
- }
-
- valueToInsert += ': ' + indentedTemplateLines.join('\n');
- templateInserted = true;
- } else {
- templateInserted = true;
- if (term.value === '[') {
- valueToInsert += '[]';
- } else if (term.value === '{') {
- valueToInsert += '{}';
- } else {
- templateInserted = false;
- }
- }
- const linesToMoveDown = (context.prefixToAdd ?? '').match(/\n|\r/g)?.length ?? 0;
-
- let prefix = context.prefixToAdd ?? '';
-
- // disable listening to the changes we are making.
- editor.off('changeSelection', editorChangeListener);
-
- // if should add chars on the previous not empty line
- if (linesToMoveDown) {
- const [firstPart = '', ...prefixPieces] = context.prefixToAdd?.split(/\n|\r/g) ?? [];
- const lastPart = _.last(prefixPieces) ?? '';
- const { start } = context.rangeToReplace!;
- const end = { ...start, column: start.column + firstPart.length };
-
- // adding only the content of prefix before newlines
- editor.replace({ start, end }, firstPart);
-
- // replacing prefix pieces without the last one, which is handled separately
- if (prefixPieces.length - 1 > 0) {
- replaceLinesWithPrefixPieces(prefixPieces, start.lineNumber);
- }
-
- // and the last prefix line, keeping the editor's own newlines.
- prefix = lastPart;
- context.rangeToReplace!.start.lineNumber = context.rangeToReplace!.end.lineNumber;
- context.rangeToReplace!.start.column = 0;
- }
-
- valueToInsert = prefix + valueToInsert + context.suffixToAdd;
-
- if (context.rangeToReplace!.start.column !== context.rangeToReplace!.end.column) {
- editor.replace(context.rangeToReplace!, valueToInsert);
- } else {
- editor.insert(valueToInsert);
- }
-
- editor.clearSelection(); // for some reason the above changes selection
-
- // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do.
- let newPos = {
- lineNumber: context.rangeToReplace!.start.lineNumber,
- column:
- context.rangeToReplace!.start.column +
- termAsString.length +
- prefix.length +
- (templateInserted ? 0 : context.suffixToAdd!.length),
- };
-
- const tokenIter = createTokenIterator({
- editor,
- position: newPos,
- });
-
- if (context.autoCompleteType === 'body') {
- // look for the next place stand, just after a comma, {
- let nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
- switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') {
- case 'paren.rparen':
- newPos = tokenIter.getCurrentPosition();
- break;
- case 'punctuation.colon':
- nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
- if ((nonEmptyToken || ({} as Token)).type === 'paren.lparen') {
- nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
- newPos = tokenIter.getCurrentPosition();
- if (nonEmptyToken && nonEmptyToken.value.indexOf('"') === 0) {
- newPos.column++;
- } // don't stand on "
- }
- break;
- case 'paren.lparen':
- case 'punctuation.comma':
- tokenIter.stepForward();
- newPos = tokenIter.getCurrentPosition();
- break;
- }
- editor.moveCursorToPosition(newPos);
- }
-
- // re-enable listening to typing
- editor.on('changeSelection', editorChangeListener);
- }
-
- function getAutoCompleteContext(ctxEditor: CoreEditor, pos: Position) {
- // deduces all the parameters need to position and insert the auto complete
- const context: AutoCompleteContext = {
- autoCompleteSet: null, // instructions for what can be here
- endpoint: null,
- urlPath: null,
- method: null,
- activeScheme: null,
- editor: ctxEditor,
- };
-
- // context.updatedForToken = session.getTokenAt(pos.row, pos.column);
- //
- // if (!context.updatedForToken)
- // context.updatedForToken = { value: "", start: pos.column }; // empty line
- //
- // context.updatedForToken.row = pos.row; // extend
-
- context.autoCompleteType = getAutoCompleteType(pos);
- switch (context.autoCompleteType) {
- case 'path':
- addPathAutoCompleteSetToContext(context, pos);
- break;
- case 'url_params':
- addUrlParamsAutoCompleteSetToContext(context, pos);
- break;
- case 'method':
- addMethodAutoCompleteSetToContext(context);
- break;
- case 'body':
- addBodyAutoCompleteSetToContext(context, pos);
- break;
- default:
- return null;
- }
-
- const isMappingsFetchingInProgress =
- context.autoCompleteType === 'body' && !!context.asyncResultsState?.isLoading;
-
- if (!context.autoCompleteSet && !isMappingsFetchingInProgress) {
- tracer('nothing to do..', context);
- return null;
- }
-
- addReplacementInfoToContext(context, pos);
-
- context.createdWithToken = _.clone(context.updatedForToken);
-
- return context;
- }
-
- function getAutoCompleteType(pos: Position) {
- // return "method", "path" or "body" to determine auto complete type.
-
- let rowMode = parser.getRowParseMode();
-
- // eslint-disable-next-line no-bitwise
- if (rowMode & parser.MODE.IN_REQUEST) {
- return 'body';
- }
- // eslint-disable-next-line no-bitwise
- if (rowMode & parser.MODE.REQUEST_START) {
- // on url path, url params or method.
- const tokenIter = createTokenIterator({
- editor,
- position: pos,
- });
- let t = tokenIter.getCurrentToken();
-
- while (t!.type === 'url.comma') {
- t = tokenIter.stepBackward();
- }
- switch (t!.type) {
- case 'method':
- return 'method';
- case 'whitespace':
- t = parser.prevNonEmptyToken(tokenIter);
-
- switch ((t || ({} as Token)).type) {
- case 'method':
- // we moved one back
- return 'path';
- break;
- default:
- if (isUrlPathToken(t)) {
- return 'path';
- }
- if (isUrlParamsToken(t)) {
- return 'url_params';
- }
- return null;
- }
- break;
- default:
- if (isUrlPathToken(t)) {
- return 'path';
- }
- if (isUrlParamsToken(t)) {
- return 'url_params';
- }
- return null;
- }
- }
-
- // after start to avoid single line url only requests
- // eslint-disable-next-line no-bitwise
- if (rowMode & parser.MODE.REQUEST_END) {
- return 'body';
- }
-
- // in between request on an empty
- if (editor.getLineValue(pos.lineNumber).trim() === '') {
- // check if the previous line is a single line beginning of a new request
- rowMode = parser.getRowParseMode(pos.lineNumber - 1);
- if (
- // eslint-disable-next-line no-bitwise
- rowMode & parser.MODE.REQUEST_START &&
- // eslint-disable-next-line no-bitwise
- rowMode & parser.MODE.REQUEST_END
- ) {
- return 'body';
- }
- // o.w suggest a method
- return 'method';
- }
-
- return null;
- }
-
- function addReplacementInfoToContext(
- context: AutoCompleteContext,
- pos: Position,
- replacingTerm?: unknown
- ) {
- // extract the initial value, rangeToReplace & textBoxPosition
-
- // Scenarios for current token:
- // - Nice token { "bla|"
- // - Broken text token { bla|
- // - No token : { |
- // - Broken scenario { , bla|
- // - Nice token, broken before: {, "bla"
-
- context.updatedForToken = _.clone(
- editor.getTokenAt({ lineNumber: pos.lineNumber, column: pos.column })
- );
- if (!context.updatedForToken) {
- context.updatedForToken = {
- value: '',
- type: '',
- position: { column: pos.column, lineNumber: pos.lineNumber },
- };
- } // empty line
-
- let anchorToken = context.createdWithToken;
- if (!anchorToken) {
- anchorToken = context.updatedForToken;
- }
-
- switch (context.updatedForToken.type) {
- case 'variable':
- case 'string':
- case 'text':
- case 'constant.numeric':
- case 'constant.language.boolean':
- case 'method':
- case 'url.index':
- case 'url.type':
- case 'url.id':
- case 'url.method':
- case 'url.endpoint':
- case 'url.part':
- case 'url.param':
- case 'url.value':
- context.rangeToReplace = {
- start: { lineNumber: pos.lineNumber, column: anchorToken.position.column },
- end: {
- lineNumber: pos.lineNumber,
- column: context.updatedForToken.position.column + context.updatedForToken.value.length,
- },
- } as Range;
- context.replacingToken = true;
- break;
- default:
- if (replacingTerm && context.updatedForToken.value === replacingTerm) {
- context.rangeToReplace = {
- start: { lineNumber: pos.lineNumber, column: anchorToken.position.column },
- end: {
- lineNumber: pos.lineNumber,
- column:
- context.updatedForToken.position.column + context.updatedForToken.value.length,
- },
- } as Range;
- context.replacingToken = true;
- } else {
- // standing on white space, quotes or another punctuation - no replacing
- context.rangeToReplace = {
- start: { lineNumber: pos.lineNumber, column: pos.column },
- end: { lineNumber: pos.lineNumber, column: pos.column },
- } as Range;
- context.replacingToken = false;
- }
- break;
- }
-
- context.textBoxPosition = {
- lineNumber: context.rangeToReplace.start.lineNumber,
- column: context.rangeToReplace.start.column,
- };
-
- switch (context.autoCompleteType) {
- case 'path':
- addPathPrefixSuffixToContext(context);
- break;
- case 'url_params':
- addUrlParamsPrefixSuffixToContext(context);
- break;
- case 'method':
- addMethodPrefixSuffixToContext(context);
- break;
- case 'body':
- addBodyPrefixSuffixToContext(context);
- break;
- }
- }
-
- function addCommaToPrefixOnAutocomplete(
- nonEmptyToken: Token | null,
- context: AutoCompleteContext,
- charsToSkipOnSameLine: number = 1
- ) {
- if (nonEmptyToken && nonEmptyToken.type.indexOf('url') < 0) {
- const { position } = nonEmptyToken;
- // if not on the first line
- if (context.rangeToReplace && context.rangeToReplace.start?.lineNumber > 1) {
- const prevTokenLineNumber = position.lineNumber;
- const editorFromContext = context.editor as CoreEditor | undefined;
- const line = editorFromContext?.getLineValue(prevTokenLineNumber) ?? '';
- const prevLineLength = line.length;
- const linesToEnter = context.rangeToReplace.end.lineNumber - prevTokenLineNumber;
-
- const isTheSameLine = linesToEnter === 0;
- let startColumn = prevLineLength + 1;
- let spaces = context.rangeToReplace.start.column - 1;
-
- if (isTheSameLine) {
- // prevent last char line from replacing
- startColumn = position.column + charsToSkipOnSameLine;
- // one char for pasted " and one for ,
- spaces = context.rangeToReplace.end.column - startColumn - 2;
- }
-
- // go back to the end of the previous line
- context.rangeToReplace = {
- start: { lineNumber: prevTokenLineNumber, column: startColumn },
- end: { ...context.rangeToReplace.end },
- };
-
- spaces = spaces >= 0 ? spaces : 0;
- const spacesToEnter = isTheSameLine ? (spaces === 0 ? 1 : spaces) : spaces;
- const newLineChars = `\n`.repeat(linesToEnter >= 0 ? linesToEnter : 0);
- const whitespaceChars = ' '.repeat(spacesToEnter);
- // add a comma at the end of the previous line, a new line and indentation
- context.prefixToAdd = `,${newLineChars}${whitespaceChars}`;
- }
- }
- }
-
- function addBodyPrefixSuffixToContext(context: AutoCompleteContext) {
- // Figure out what happens next to the token to see whether it needs trailing commas etc.
-
- // Templates will be used if not destroying existing structure.
- // -> token : {} or token ]/} or token , but not token : SOMETHING ELSE
-
- context.prefixToAdd = '';
- context.suffixToAdd = '';
-
- let tokenIter = createTokenIterator({
- editor,
- position: editor.getCurrentPosition()!,
- });
- let nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
- switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') {
- case 'NOTOKEN':
- case 'paren.lparen':
- case 'paren.rparen':
- case 'punctuation.comma':
- context.addTemplate = true;
- break;
- case 'punctuation.colon':
- // test if there is an empty object - if so we replace it
- context.addTemplate = false;
-
- nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
- if (!(nonEmptyToken && nonEmptyToken.value === '{')) {
- break;
- }
- nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
- if (!(nonEmptyToken && nonEmptyToken.value === '}')) {
- break;
- }
- context.addTemplate = true;
- // extend range to replace to include all up to token
- context.rangeToReplace!.end.lineNumber = tokenIter.getCurrentTokenLineNumber() as number;
- context.rangeToReplace!.end.column =
- (tokenIter.getCurrentTokenColumn() as number) + nonEmptyToken.value.length;
-
- // move one more time to check if we need a trailing comma
- nonEmptyToken = parser.nextNonEmptyToken(tokenIter);
- switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') {
- case 'NOTOKEN':
- case 'paren.rparen':
- case 'punctuation.comma':
- case 'punctuation.colon':
- break;
- default:
- context.suffixToAdd = ', ';
- }
-
- break;
- default:
- context.addTemplate = true;
- context.suffixToAdd = ', ';
- break; // for now play safe and do nothing. May be made smarter.
- }
-
- // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do.
- tokenIter = createTokenIterator({ editor, position: editor.getCurrentPosition() });
- nonEmptyToken = tokenIter.getCurrentToken();
- let insertingRelativeToToken; // -1 is before token, 0 middle, +1 after token
- if (context.replacingToken) {
- insertingRelativeToToken = 0;
- } else {
- const pos = editor.getCurrentPosition();
- if (pos.column === context.updatedForToken!.position.column) {
- insertingRelativeToToken = -1;
- } else if (
- pos.column <
- context.updatedForToken!.position.column + context.updatedForToken!.value.length
- ) {
- insertingRelativeToToken = 0;
- } else {
- insertingRelativeToToken = 1;
- }
- }
- // we should actually look at what's happening before this token
- if (parser.isEmptyToken(nonEmptyToken) || insertingRelativeToToken <= 0) {
- nonEmptyToken = parser.prevNonEmptyToken(tokenIter);
- }
-
- switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') {
- case 'NOTOKEN':
- case 'paren.lparen':
- case 'punctuation.comma':
- case 'punctuation.colon':
- case 'punctuation.start_triple_quote':
- case 'method':
- break;
- case 'text':
- case 'string':
- case 'constant.numeric':
- case 'constant.language.boolean':
- case 'punctuation.end_triple_quote':
- addCommaToPrefixOnAutocomplete(nonEmptyToken, context, nonEmptyToken?.value.length);
- break;
- default:
- addCommaToPrefixOnAutocomplete(nonEmptyToken, context);
- break;
- }
-
- return context;
- }
-
- function addUrlParamsPrefixSuffixToContext(context: AutoCompleteContext) {
- context.prefixToAdd = '';
- context.suffixToAdd = '';
- }
-
- function addMethodPrefixSuffixToContext(context: AutoCompleteContext) {
- context.prefixToAdd = '';
- context.suffixToAdd = '';
- const tokenIter = createTokenIterator({ editor, position: editor.getCurrentPosition() });
- const lineNumber = tokenIter.getCurrentPosition().lineNumber;
- const t = parser.nextNonEmptyToken(tokenIter);
-
- if (tokenIter.getCurrentPosition().lineNumber !== lineNumber || !t) {
- // we still have nothing next to the method, add a space..
- context.suffixToAdd = ' ';
- }
- }
-
- function addPathPrefixSuffixToContext(context: AutoCompleteContext) {
- context.prefixToAdd = '';
- context.suffixToAdd = '';
- }
-
- function addMethodAutoCompleteSetToContext(context: AutoCompleteContext) {
- context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD', 'PATCH'].map((m, i) => ({
- name: m,
- score: -i,
- meta: i18n.translate('console.autocomplete.addMethodMetaText', { defaultMessage: 'method' }),
- }));
- }
-
- function addPathAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
- const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
- context.method = ret.method?.toUpperCase();
- context.token = ret.token;
- context.otherTokenValues = ret.otherTokenValues;
- context.urlTokenPath = ret.urlTokenPath;
-
- const components = getTopLevelUrlCompleteComponents(context.method);
- let urlTokenPath = context.urlTokenPath;
- let predicate: (term: ResultTerm) => boolean = () => true;
-
- const tokenIter = createTokenIterator({ editor, position: pos });
- const currentTokenType = tokenIter.getCurrentToken()?.type;
- const previousTokenType = tokenIter.stepBackward()?.type;
- if (!Array.isArray(urlTokenPath)) {
- // skip checks for url.comma
- } else if (previousTokenType === 'url.comma' && currentTokenType === 'url.comma') {
- predicate = () => false; // two consecutive commas empty the autocomplete
- } else if (
- (previousTokenType === 'url.part' && currentTokenType === 'url.comma') ||
- (previousTokenType === 'url.slash' && currentTokenType === 'url.comma') ||
- (previousTokenType === 'url.comma' && currentTokenType === 'url.part')
- ) {
- const lastUrlTokenPath = _.last(urlTokenPath) || []; // ['c', 'd'] from 'GET /a/b/c,d,'
- const constantComponents = _.filter(components, (c) => c instanceof ConstantComponent);
- const constantComponentNames = _.map(constantComponents, 'name');
-
- // check if neither 'c' nor 'd' is a constant component name such as '_search'
- if (_.every(lastUrlTokenPath, (token) => !_.includes(constantComponentNames, token))) {
- urlTokenPath = urlTokenPath.slice(0, -1); // drop the last 'c,d,' part from the url path
- predicate = (term) => term.meta === 'index'; // limit the autocomplete to indices only
- }
- }
-
- populateContext(urlTokenPath, context, editor, true, components);
- context.autoCompleteSet = _.filter(
- addMetaToTermsList(context.autoCompleteSet!, 'endpoint'),
- predicate
- );
- }
-
- function addUrlParamsAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
- const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
- context.method = ret.method;
- context.otherTokenValues = ret.otherTokenValues;
- context.urlTokenPath = ret.urlTokenPath;
- if (!ret.urlTokenPath) {
- // zero length tokenPath is true
-
- return context;
- }
-
- populateContext(
- ret.urlTokenPath,
- context,
- editor,
- false,
- getTopLevelUrlCompleteComponents(context.method)
- );
-
- if (!context.endpoint) {
- return context;
- }
-
- if (!ret.urlParamsTokenPath) {
- // zero length tokenPath is true
- return context;
- }
- let tokenPath: string[] = [];
- const currentParam = ret.urlParamsTokenPath.pop();
- if (currentParam) {
- tokenPath = Object.keys(currentParam); // single key object
- context.otherTokenValues = currentParam[tokenPath[0]];
- }
-
- populateContext(
- tokenPath,
- context,
- editor,
- true,
- context.endpoint.paramsAutocomplete.getTopLevelComponents(context.method)
- );
- return context;
- }
-
- function addBodyAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
- const ret = getCurrentMethodAndTokenPaths(editor, pos, parser);
- context.method = ret.method;
- context.otherTokenValues = ret.otherTokenValues;
- context.urlTokenPath = ret.urlTokenPath;
- context.requestStartRow = ret.requestStartRow;
- if (!ret.urlTokenPath) {
- // zero length tokenPath is true
- return context;
- }
-
- populateContext(
- ret.urlTokenPath,
- context,
- editor,
- false,
- getTopLevelUrlCompleteComponents(context.method)
- );
-
- context.bodyTokenPath = ret.bodyTokenPath;
- if (!ret.bodyTokenPath) {
- // zero length tokenPath is true
-
- return context;
- }
-
- const t = editor.getTokenAt(pos);
- if (t && t.type === 'punctuation.end_triple_quote' && pos.column !== t.position.column + 3) {
- // skip to populate context as the current position is not on the edge of end_triple_quote
- return context;
- }
-
- // needed for scope linking + global term resolving
- context.endpointComponentResolver = getEndpointBodyCompleteComponents;
- context.globalComponentResolver = getGlobalAutocompleteComponents;
- let components: unknown;
- if (context.endpoint) {
- components = context.endpoint.bodyAutocompleteRootComponents;
- } else {
- components = getUnmatchedEndpointComponents();
- }
- populateContext(ret.bodyTokenPath, context, editor, true, components);
-
- return context;
- }
-
- const evaluateCurrentTokenAfterAChange = _.debounce(function evaluateCurrentTokenAfterAChange(
- pos: Position
- ) {
- let currentToken = editor.getTokenAt(pos)!;
- tracer('has started evaluating current token', currentToken);
-
- if (!currentToken) {
- lastEvaluatedToken = null;
- currentToken = { position: { column: 0, lineNumber: 0 }, value: '', type: '' }; // empty row
- }
-
- currentToken.position.lineNumber = pos.lineNumber; // extend token with row. Ace doesn't supply it by default
- if (parser.isEmptyToken(currentToken)) {
- // empty token. check what's coming next
- const nextToken = editor.getTokenAt({ ...pos, column: pos.column + 1 })!;
- if (parser.isEmptyToken(nextToken)) {
- // Empty line, or we're not on the edge of current token. Save the current position as base
- currentToken.position.column = pos.column;
- lastEvaluatedToken = currentToken;
- } else {
- nextToken.position.lineNumber = pos.lineNumber;
- lastEvaluatedToken = nextToken;
- }
- tracer('not starting autocomplete due to empty current token');
- return;
- }
-
- if (!lastEvaluatedToken) {
- lastEvaluatedToken = currentToken;
- tracer('not starting autocomplete due to invalid last evaluated token');
- return; // wait for the next typing.
- }
-
- if (!looksLikeTypingIn(lastEvaluatedToken, currentToken, editor)) {
- tracer('not starting autocomplete', lastEvaluatedToken, '->', currentToken);
- // not on the same place or nothing changed, cache and wait for the next time
- lastEvaluatedToken = currentToken;
- return;
- }
-
- // don't automatically open the auto complete if some just hit enter (new line) or open a parentheses
- switch (currentToken.type || 'UNKNOWN') {
- case 'paren.lparen':
- case 'paren.rparen':
- case 'punctuation.colon':
- case 'punctuation.comma':
- case 'comment.line':
- case 'comment.punctuation':
- case 'comment.block':
- case 'UNKNOWN':
- tracer('not starting autocomplete for current token type', currentToken.type);
- return;
- }
-
- tracer('starting autocomplete', lastEvaluatedToken, '->', currentToken);
- lastEvaluatedToken = currentToken;
- editor.execCommand('startAutocomplete');
- },
- 100);
-
- function editorChangeListener() {
- const position = editor.getCurrentPosition();
- tracer('editor changed', position);
- if (position && !editor.isCompleterActive()) {
- tracer('will start evaluating current token');
- evaluateCurrentTokenAfterAChange(position);
- }
- }
-
- /**
- * Extracts terms from the autocomplete set.
- * @param context
- */
- function getTerms(context: AutoCompleteContext, autoCompleteSet: ResultTerm[]) {
- const terms = _.map(
- autoCompleteSet.filter((term) => Boolean(term) && term.name != null),
- function (term) {
- if (typeof term !== 'object') {
- term = {
- name: term,
- };
- } else {
- term = _.clone(term);
- }
- const defaults: {
- value?: string;
- meta: string;
- score: number;
- context: AutoCompleteContext;
- completer?: { insertMatch: (v: unknown) => void };
- } = {
- value: term.name + '',
- meta: 'API',
- score: 0,
- context,
- };
- // we only need our custom insertMatch behavior for the body
- if (context.autoCompleteType === 'body') {
- defaults.completer = {
- insertMatch() {
- return applyTerm(term);
- },
- };
- }
- return _.defaults(term, defaults);
- }
- );
-
- terms.sort(function (
- t1: { score: number; name?: string | boolean },
- t2: { score: number; name?: string | boolean }
- ) {
- /* score sorts from high to low */
- if (t1.score > t2.score) {
- return -1;
- }
- if (t1.score < t2.score) {
- return 1;
- }
- /* names sort from low to high */
- if (t1.name! < t2.name!) {
- return -1;
- }
- if (t1.name === t2.name) {
- return 0;
- }
- return 1;
- });
-
- return terms;
- }
-
- function getSuggestions(terms: ResultTerm[]) {
- return _.map(terms, function (t, i) {
- t.insertValue = t.insertValue || t.value;
- t.value = '' + t.value; // normalize to strings
- t.score = -i;
- return t;
- });
- }
-
- function getCompletions(
- position: Position,
- prefix: string,
- callback: (e: Error | null, result: ResultTerm[] | null) => void,
- annotationControls: {
- setAnnotation: (text: string) => void;
- removeAnnotation: () => void;
- }
- ) {
- try {
- const context = getAutoCompleteContext(editor, position);
-
- if (!context) {
- tracer('zero suggestions due to invalid autocomplete context');
- callback(null, []);
- } else {
- if (!context.asyncResultsState?.isLoading) {
- const terms = getTerms(context, context.autoCompleteSet!);
- const suggestions = getSuggestions(terms);
- tracer(suggestions?.length ?? 0, 'suggestions');
- callback(null, suggestions);
- }
-
- if (context.asyncResultsState) {
- annotationControls.setAnnotation(
- i18n.translate('console.autocomplete.fieldsFetchingAnnotation', {
- defaultMessage: 'Fields fetching is in progress',
- })
- );
-
- context.asyncResultsState.results.then((r) => {
- const asyncSuggestions = getSuggestions(getTerms(context, r));
- tracer(asyncSuggestions?.length ?? 0, 'async suggestions');
- callback(null, asyncSuggestions);
- annotationControls.removeAnnotation();
- });
- }
- }
- } catch (e) {
- // eslint-disable-next-line no-console
- console.error(e);
- callback(e, null);
- }
- }
-
- editor.on('changeSelection', editorChangeListener);
-
- return {
- getCompletions,
- // TODO: This needs to be cleaned up
- _test: {
- getCompletions: (
- _editor: unknown,
- _editSession: unknown,
- pos: Position,
- prefix: string,
- callback: (e: Error | null, result: ResultTerm[] | null) => void,
- annotationControls: {
- setAnnotation: (text: string) => void;
- removeAnnotation: () => void;
- }
- ) => getCompletions(pos, prefix, callback, annotationControls),
- addReplacementInfoToContext,
- addChangeListener: () => editor.on('changeSelection', editorChangeListener),
- removeChangeListener: () => editor.off('changeSelection', editorChangeListener),
- },
- };
-}
diff --git a/src/plugins/console/public/lib/autocomplete/get_endpoint_from_position.ts b/src/plugins/console/public/lib/autocomplete/get_endpoint_from_position.ts
deleted file mode 100644
index b65e277e41723..0000000000000
--- a/src/plugins/console/public/lib/autocomplete/get_endpoint_from_position.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { CoreEditor, Position } from '../../types';
-import { getCurrentMethodAndTokenPaths } from './autocomplete';
-import type RowParser from '../row_parser';
-
-import { getTopLevelUrlCompleteComponents } from '../kb/kb';
-import { populateContext } from './engine';
-
-export function getEndpointFromPosition(editor: CoreEditor, pos: Position, parser: RowParser) {
- const lineValue = editor.getLineValue(pos.lineNumber);
- const context = {
- ...getCurrentMethodAndTokenPaths(
- editor,
- {
- column: lineValue.length + 1 /* Go to the very end of the line */,
- lineNumber: pos.lineNumber,
- },
- parser,
- true
- ),
- };
- const components = getTopLevelUrlCompleteComponents(context.method);
- populateContext(context.urlTokenPath, context, editor, true, components);
- return context.endpoint;
-}
diff --git a/src/plugins/console/public/lib/autocomplete/looks_like_typing_in.test.ts b/src/plugins/console/public/lib/autocomplete/looks_like_typing_in.test.ts
deleted file mode 100644
index 101fd96a79024..0000000000000
--- a/src/plugins/console/public/lib/autocomplete/looks_like_typing_in.test.ts
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import '../../application/models/sense_editor/sense_editor.test.mocks';
-
-import { looksLikeTypingIn } from './looks_like_typing_in';
-import { create } from '../../application/models';
-import type { SenseEditor } from '../../application/models';
-import type { CoreEditor, Position, Token, TokensProvider } from '../../types';
-
-describe('looksLikeTypingIn', () => {
- let editor: SenseEditor;
- let coreEditor: CoreEditor;
- let tokenProvider: TokensProvider;
-
- beforeEach(() => {
- document.body.innerHTML = ``;
- editor = create(document.getElementById('ConAppEditor')!);
- coreEditor = editor.getCoreEditor();
- tokenProvider = coreEditor.getTokenProvider();
- });
-
- afterEach(async () => {
- await editor.update('', true);
- });
-
- describe('general typing in', () => {
- interface RunTestArgs {
- preamble: string;
- autocomplete?: string;
- input: string;
- }
-
- const runTest = async ({ preamble, autocomplete, input }: RunTestArgs) => {
- const pos: Position = { lineNumber: 1, column: 1 };
-
- await editor.update(preamble, true);
- pos.column += preamble.length;
- const lastEvaluatedToken = tokenProvider.getTokenAt(pos);
-
- if (autocomplete !== undefined) {
- await editor.update(coreEditor.getValue() + autocomplete, true);
- pos.column += autocomplete.length;
- }
-
- await editor.update(coreEditor.getValue() + input, true);
- pos.column += input.length;
- const currentToken = tokenProvider.getTokenAt(pos);
-
- expect(lastEvaluatedToken).not.toBeNull();
- expect(currentToken).not.toBeNull();
- expect(looksLikeTypingIn(lastEvaluatedToken!, currentToken!, coreEditor)).toBe(true);
- };
-
- const cases: RunTestArgs[] = [
- { preamble: 'G', input: 'E' },
- { preamble: 'GET .kibana', input: '/' },
- { preamble: 'GET .kibana', input: ',' },
- { preamble: 'GET .kibana', input: '?' },
- { preamble: 'GET .kibana/', input: '_' },
- { preamble: 'GET .kibana/', input: '?' },
- { preamble: 'GET .kibana,', input: '.' },
- { preamble: 'GET .kibana,', input: '?' },
- { preamble: 'GET .kibana?', input: 'k' },
- { preamble: 'GET .kibana?k', input: '=' },
- { preamble: 'GET .kibana?k=', input: 'v' },
- { preamble: 'GET .kibana?k=v', input: '&' },
- { preamble: 'GET .kibana?k', input: '&' },
- { preamble: 'GET .kibana?k&', input: 'k' },
- { preamble: 'GET ', autocomplete: '.kibana', input: '/' },
- { preamble: 'GET ', autocomplete: '.kibana', input: ',' },
- { preamble: 'GET ', autocomplete: '.kibana', input: '?' },
- { preamble: 'GET .ki', autocomplete: 'bana', input: '/' },
- { preamble: 'GET .ki', autocomplete: 'bana', input: ',' },
- { preamble: 'GET .ki', autocomplete: 'bana', input: '?' },
- { preamble: 'GET _nodes/', autocomplete: 'stats', input: '/' },
- { preamble: 'GET _nodes/sta', autocomplete: 'ts', input: '/' },
- { preamble: 'GET _nodes/', autocomplete: 'jvm', input: ',' },
- { preamble: 'GET _nodes/j', autocomplete: 'vm', input: ',' },
- { preamble: 'GET _nodes/jvm,', autocomplete: 'os', input: ',' },
- { preamble: 'GET .kibana,', autocomplete: '.security', input: ',' },
- { preamble: 'GET .kibana,.sec', autocomplete: 'urity', input: ',' },
- { preamble: 'GET .kibana,', autocomplete: '.security', input: '/' },
- { preamble: 'GET .kibana,.sec', autocomplete: 'urity', input: '/' },
- { preamble: 'GET .kibana,', autocomplete: '.security', input: '?' },
- { preamble: 'GET .kibana,.sec', autocomplete: 'urity', input: '?' },
- { preamble: 'GET .kibana/', autocomplete: '_search', input: '?' },
- { preamble: 'GET .kibana/_se', autocomplete: 'arch', input: '?' },
- { preamble: 'GET .kibana/_search?', autocomplete: 'expand_wildcards', input: '=' },
- { preamble: 'GET .kibana/_search?exp', autocomplete: 'and_wildcards', input: '=' },
- { preamble: 'GET .kibana/_search?expand_wildcards=', autocomplete: 'all', input: '&' },
- { preamble: 'GET .kibana/_search?expand_wildcards=a', autocomplete: 'll', input: '&' },
- { preamble: 'GET _cat/indices?s=index&', autocomplete: 'expand_wildcards', input: '=' },
- { preamble: 'GET _cat/indices?s=index&exp', autocomplete: 'and_wildcards', input: '=' },
- { preamble: 'GET _cat/indices?v&', autocomplete: 'expand_wildcards', input: '=' },
- { preamble: 'GET _cat/indices?v&exp', autocomplete: 'and_wildcards', input: '=' },
- // autocomplete skips one iteration of token evaluation if user types in every letter
- { preamble: 'GET .kibana', autocomplete: '/', input: '_' }, // token '/' may not be evaluated
- { preamble: 'GET .kibana', autocomplete: ',', input: '.' }, // token ',' may not be evaluated
- { preamble: 'GET .kibana', autocomplete: '?', input: 'k' }, // token '?' may not be evaluated
- ];
- for (const c of cases) {
- const name =
- c.autocomplete === undefined
- ? `'${c.preamble}' -> '${c.input}'`
- : `'${c.preamble}' -> '${c.autocomplete}' (autocomplte) -> '${c.input}'`;
- test(name, async () => runTest(c));
- }
- });
-
- describe('first typing in', () => {
- test(`'' -> 'G'`, () => {
- // this is based on an implementation within the evaluateCurrentTokenAfterAChange function
- const lastEvaluatedToken = { position: { column: 0, lineNumber: 0 }, value: '', type: '' };
- lastEvaluatedToken.position.lineNumber = coreEditor.getCurrentPosition().lineNumber;
-
- const currentToken = { position: { column: 1, lineNumber: 1 }, value: 'G', type: 'method' };
- expect(looksLikeTypingIn(lastEvaluatedToken, currentToken, coreEditor)).toBe(true);
- });
- });
-
- const matrices = [
- `
-GET .kibana/
-
-
-`
- .slice(1, -1)
- .split('\n'),
- `
-
- POST test/_doc
-{"message": "test"}
-
-GET /_cat/indices?v&s=
-
-DE
-`
- .slice(1, -1)
- .split('\n'),
- `
-
-PUT test/_doc/1
-{"field": "value"}
-`
- .slice(1, -1)
- .split('\n'),
- ];
-
- describe('navigating the editor via keyboard arrow keys', () => {
- const runHorizontalZigzagWalkTest = async (matrix: string[]) => {
- const width = matrix[0].length;
- const height = matrix.length;
-
- await editor.update(matrix.join('\n'), true);
- let lastEvaluatedToken = tokenProvider.getTokenAt(coreEditor.getCurrentPosition());
- let currentToken: Token | null;
-
- for (let i = 1; i < height * width * 2; i++) {
- const pos = {
- column: 1 + (i % width),
- lineNumber: 1 + Math.floor(i / width),
- };
- if (pos.lineNumber % 2 === 0) {
- pos.column = width - pos.column + 1;
- }
- if (pos.lineNumber > height) {
- pos.lineNumber = 2 * height - pos.lineNumber + 1;
- }
-
- currentToken = tokenProvider.getTokenAt(pos);
- expect(lastEvaluatedToken).not.toBeNull();
- expect(currentToken).not.toBeNull();
- expect(looksLikeTypingIn(lastEvaluatedToken!, currentToken!, coreEditor)).toBe(false);
- lastEvaluatedToken = currentToken;
- }
- };
-
- for (const matrix of matrices) {
- test(`horizontal zigzag walk ${matrix[0].length}x${matrix.length} map`, () =>
- runHorizontalZigzagWalkTest(matrix));
- }
- });
-
- describe('clicking around the editor', () => {
- const runRandomClickingTest = async (matrix: string[], attempts: number) => {
- const width = matrix[0].length;
- const height = matrix.length;
-
- await editor.update(matrix.join('\n'), true);
- let lastEvaluatedToken = tokenProvider.getTokenAt(coreEditor.getCurrentPosition());
- let currentToken: Token | null;
-
- for (let i = 1; i < attempts; i++) {
- const pos = {
- column: Math.ceil(Math.random() * width),
- lineNumber: Math.ceil(Math.random() * height),
- };
-
- currentToken = tokenProvider.getTokenAt(pos);
- expect(lastEvaluatedToken).not.toBeNull();
- expect(currentToken).not.toBeNull();
- expect(looksLikeTypingIn(lastEvaluatedToken!, currentToken!, coreEditor)).toBe(false);
- lastEvaluatedToken = currentToken;
- }
- };
-
- for (const matrix of matrices) {
- const attempts = 4 * matrix[0].length * matrix.length;
- test(`random clicking ${matrix[0].length}x${matrix.length} map ${attempts} times`, () =>
- runRandomClickingTest(matrix, attempts));
- }
- });
-});
diff --git a/src/plugins/console/public/lib/autocomplete/looks_like_typing_in.ts b/src/plugins/console/public/lib/autocomplete/looks_like_typing_in.ts
deleted file mode 100644
index a22c985a943f6..0000000000000
--- a/src/plugins/console/public/lib/autocomplete/looks_like_typing_in.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import type { CoreEditor, Position, Token } from '../../types';
-
-enum Move {
- ForwardOneCharacter = 1,
- ForwardOneToken, // the column position may jump to the next token by autocomplete
- ForwardTwoTokens, // the column position could jump two tokens due to autocomplete
-}
-
-const knownTypingInTokenTypes = new Map>>([
- [
- Move.ForwardOneCharacter,
- new Map>([
- // a pair of the last evaluated token type and a set of the current token types
- ['', new Set(['method'])],
- ['url.amp', new Set(['url.param'])],
- ['url.comma', new Set(['url.part', 'url.questionmark'])],
- ['url.equal', new Set(['url.value'])],
- ['url.param', new Set(['url.amp', 'url.equal'])],
- ['url.questionmark', new Set(['url.param'])],
- ['url.slash', new Set(['url.part', 'url.questionmark'])],
- ['url.value', new Set(['url.amp'])],
- ]),
- ],
- [
- Move.ForwardOneToken,
- new Map>([
- ['method', new Set(['url.part'])],
- ['url.amp', new Set(['url.amp', 'url.equal'])],
- ['url.comma', new Set(['url.comma', 'url.questionmark', 'url.slash'])],
- ['url.equal', new Set(['url.amp'])],
- ['url.param', new Set(['url.equal'])],
- ['url.part', new Set(['url.comma', 'url.questionmark', 'url.slash'])],
- ['url.questionmark', new Set(['url.equal'])],
- ['url.slash', new Set(['url.comma', 'url.questionmark', 'url.slash'])],
- ['url.value', new Set(['url.amp'])],
- ['whitespace', new Set(['url.comma', 'url.questionmark', 'url.slash'])],
- ]),
- ],
- [
- Move.ForwardTwoTokens,
- new Map>([['url.part', new Set(['url.param', 'url.part'])]]),
- ],
-]);
-
-const getOneCharacterNextOnTheRight = (pos: Position, coreEditor: CoreEditor): string => {
- const range = {
- start: { column: pos.column + 1, lineNumber: pos.lineNumber },
- end: { column: pos.column + 2, lineNumber: pos.lineNumber },
- };
- return coreEditor.getValueInRange(range);
-};
-
-/**
- * Examines a change from the last evaluated to the current token and one
- * character next to the current token position on the right. Returns true if
- * the change looks like typing in, false otherwise.
- *
- * This function is supposed to filter out situations where autocomplete is not
- * preferable, such as clicking around the editor, navigating the editor via
- * keyboard arrow keys, etc.
- */
-export const looksLikeTypingIn = (
- lastEvaluatedToken: Token,
- currentToken: Token,
- coreEditor: CoreEditor
-): boolean => {
- // if the column position moves to the right in the same line and the current
- // token length is 1, then user is possibly typing in a character.
- if (
- lastEvaluatedToken.position.column < currentToken.position.column &&
- lastEvaluatedToken.position.lineNumber === currentToken.position.lineNumber &&
- currentToken.value.length === 1 &&
- getOneCharacterNextOnTheRight(currentToken.position, coreEditor) === ''
- ) {
- const moves =
- lastEvaluatedToken.position.column + 1 === currentToken.position.column
- ? [Move.ForwardOneCharacter]
- : [Move.ForwardOneToken, Move.ForwardTwoTokens];
- for (const move of moves) {
- const tokenTypesPairs = knownTypingInTokenTypes.get(move) ?? new Map>();
- const currentTokenTypes = tokenTypesPairs.get(lastEvaluatedToken.type) ?? new Set();
- if (currentTokenTypes.has(currentToken.type)) {
- return true;
- }
- }
- }
-
- // if the column or the line number have changed for the last token or
- // user did not provided a new value, then we should not show autocomplete
- // this guards against triggering autocomplete when clicking around the editor
- if (
- lastEvaluatedToken.position.column !== currentToken.position.column ||
- lastEvaluatedToken.position.lineNumber !== currentToken.position.lineNumber ||
- lastEvaluatedToken.value === currentToken.value
- ) {
- return false;
- }
-
- return true;
-};
diff --git a/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js b/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js
index 5901c95b9a074..0cffb157abb4c 100644
--- a/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js
+++ b/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js
@@ -7,7 +7,6 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
-import '../../application/models/sense_editor/sense_editor.test.mocks';
import { setAutocompleteInfo, AutocompleteInfo } from '../../services';
import { expandAliases } from './expand_aliases';
import { httpServiceMock } from '@kbn/core-http-browser-mocks';
diff --git a/src/plugins/console/public/lib/curl_parsing/__fixtures__/curl_parsing.txt b/src/plugins/console/public/lib/curl_parsing/__fixtures__/curl_parsing.txt
deleted file mode 100644
index b6dd39479550d..0000000000000
--- a/src/plugins/console/public/lib/curl_parsing/__fixtures__/curl_parsing.txt
+++ /dev/null
@@ -1,146 +0,0 @@
-==========
-Curl 1
--------------------------------------
-curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{
- "user" : "kimchy",
- "post_date" : "2009-11-15T14:12:12",
- "message" : "trying out Elastic Search"
-}'
--------------------------------------
-PUT /twitter/tweet/1
-{
- "user" : "kimchy",
- "post_date" : "2009-11-15T14:12:12",
- "message" : "trying out Elastic Search"
-}
-==========
-Curl 2
--------------------------------------
-curl -XGET "localhost/twitter/tweet/1?version=2" -d '{
- "message" : "elasticsearch now has versioning support, double cool!"
-}'
--------------------------------------
-GET /twitter/tweet/1?version=2
-{
- "message" : "elasticsearch now has versioning support, double cool!"
-}
-===========
-Curl 3
--------------------------------------
-curl -XPOST https://localhost/twitter/tweet/1?version=2 -d '{
- "message" : "elasticsearch now has versioning support, double cool!"
-}'
--------------------------------------
-POST /twitter/tweet/1?version=2
-{
- "message" : "elasticsearch now has versioning support, double cool!"
-}
-=========
-Curl 4
--------------------------------------
-curl -XPOST https://localhost/twitter
--------------------------------------
-POST /twitter
-==========
-Curl 5
--------------------------------------
-curl -X POST https://localhost/twitter/
--------------------------------------
-POST /twitter/
-=============
-Curl 6
--------------------------------------
-curl -s -XPOST localhost:9200/missing-test -d'
-{
- "mappings": {
- }
-}'
--------------------------------------
-POST /missing-test
-{
- "mappings": {
- }
-}
-=========================
-Curl 7
--------------------------------------
-curl 'localhost:9200/missing-test/doc/_search?pretty' -d'
-{
- "query": {
- },
-}'
--------------------------------------
-GET /missing-test/doc/_search?pretty
-{
- "query": {
- },
-}
-===========================
-Curl 8
--------------------------------------
-curl localhost:9200/ -d'
-{
- "query": {
- }
-}'
--------------------------------------
-GET /
-{
- "query": {
- }
-}
-====================================
-Curl Script
--------------------------------------
-#!bin/sh
-
-// test something
-curl 'localhost:9200/missing-test/doc/_search?pretty' -d'
-{
- "query": {
- },
-}'
-
-
-curl -XPOST https://localhost/twitter
-
-#someother comments
-curl localhost:9200/ -d'
-{
- "query": {
- }
-}'
-
-
--------------------
-# test something
-GET /missing-test/doc/_search?pretty
-{
- "query": {
- },
-}
-
-POST /twitter
-
-#someother comments
-GET /
-{
- "query": {
- }
-}
-====================================
-Curl with some text
--------------------------------------
-This is what I meant:
-
-curl 'localhost:9200/missing-test/doc/_search?'
-
-This, however, does work:
-curl 'localhost:9200/missing/doc/_search?'
--------------------
-### This is what I meant:
-
-GET /missing-test/doc/_search?
-
-### This, however, does work:
-GET /missing/doc/_search?
diff --git a/src/plugins/console/public/lib/curl_parsing/curl.js b/src/plugins/console/public/lib/curl_parsing/curl.js
deleted file mode 100644
index 4dd09d1b7d59b..0000000000000
--- a/src/plugins/console/public/lib/curl_parsing/curl.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-function detectCURLinLine(line) {
- // returns true if text matches a curl request
- return line.match(/^\s*?curl\s+(-X[A-Z]+)?\s*['"]?.*?['"]?(\s*$|\s+?-d\s*?['"])/);
-}
-
-export function detectCURL(text) {
- // returns true if text matches a curl request
- if (!text) return false;
- for (const line of text.split('\n')) {
- if (detectCURLinLine(line)) {
- return true;
- }
- }
- return false;
-}
-
-export function parseCURL(text) {
- let state = 'NONE';
- const out = [];
- let body = [];
- let line = '';
- const lines = text.trim().split('\n');
- let matches;
-
- const EmptyLine = /^\s*$/;
- const Comment = /^\s*(?:#|\/{2,})(.*)\n?$/;
- const ExecutionComment = /^\s*#!/;
- const ClosingSingleQuote = /^([^']*)'/;
- const ClosingDoubleQuote = /^((?:[^\\"]|\\.)*)"/;
- const EscapedQuotes = /^((?:[^\\"']|\\.)+)/;
-
- const LooksLikeCurl = /^\s*curl\s+/;
- const CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE|PATCH)/;
-
- const HasProtocol = /[\s"']https?:\/\//;
- const CurlRequestWithProto = /[\s"']https?:\/\/[^\/ ]+\/+([^\s"']+)/;
- const CurlRequestWithoutProto = /[\s"'][^\/ ]+\/+([^\s"']+)/;
- const CurlData = /^.+\s(--data|-d)\s*/;
- const SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE|PATCH)\s+\/?(.+)/;
-
- if (lines.length > 0 && ExecutionComment.test(lines[0])) {
- lines.shift();
- }
-
- function nextLine() {
- if (line.length > 0) {
- return true;
- }
- if (lines.length === 0) {
- return false;
- }
- line = lines.shift().replace(/[\r\n]+/g, '\n') + '\n';
- return true;
- }
-
- function unescapeLastBodyEl() {
- const str = body.pop().replace(/\\([\\"'])/g, '$1');
- body.push(str);
- }
-
- // Is the next char a single or double quote?
- // If so remove it
- function detectQuote() {
- if (line.substr(0, 1) === "'") {
- line = line.substr(1);
- state = 'SINGLE_QUOTE';
- } else if (line.substr(0, 1) === '"') {
- line = line.substr(1);
- state = 'DOUBLE_QUOTE';
- } else {
- state = 'UNQUOTED';
- }
- }
-
- // Body is finished - append to output with final LF
- function addBodyToOut() {
- if (body.length > 0) {
- out.push(body.join(''));
- body = [];
- }
- state = 'LF';
- out.push('\n');
- }
-
- // If the pattern matches, then the state is about to change,
- // so add the capture to the body and detect the next state
- // Otherwise add the whole line
- function consumeMatching(pattern) {
- const matches = line.match(pattern);
- if (matches) {
- body.push(matches[1]);
- line = line.substr(matches[0].length);
- detectQuote();
- } else {
- body.push(line);
- line = '';
- }
- }
-
- function parseCurlLine() {
- let verb = 'GET';
- let request = '';
- let matches;
- if ((matches = line.match(CurlVerb))) {
- verb = matches[1];
- }
-
- // JS regexen don't support possessive quantifiers, so
- // we need two distinct patterns
- const pattern = HasProtocol.test(line) ? CurlRequestWithProto : CurlRequestWithoutProto;
-
- if ((matches = line.match(pattern))) {
- request = matches[1];
- }
-
- out.push(verb + ' /' + request + '\n');
-
- if ((matches = line.match(CurlData))) {
- line = line.substr(matches[0].length);
- detectQuote();
- if (EmptyLine.test(line)) {
- line = '';
- }
- } else {
- state = 'NONE';
- line = '';
- out.push('');
- }
- }
-
- while (nextLine()) {
- if (state === 'SINGLE_QUOTE') {
- consumeMatching(ClosingSingleQuote);
- } else if (state === 'DOUBLE_QUOTE') {
- consumeMatching(ClosingDoubleQuote);
- unescapeLastBodyEl();
- } else if (state === 'UNQUOTED') {
- consumeMatching(EscapedQuotes);
- if (body.length) {
- unescapeLastBodyEl();
- }
- if (state === 'UNQUOTED') {
- addBodyToOut();
- line = '';
- }
- }
-
- // the BODY state (used to match the body of a Sense request)
- // can be terminated early if it encounters
- // a comment or an empty line
- else if (state === 'BODY') {
- if (Comment.test(line) || EmptyLine.test(line)) {
- addBodyToOut();
- } else {
- body.push(line);
- line = '';
- }
- } else if (EmptyLine.test(line)) {
- if (state !== 'LF') {
- out.push('\n');
- state = 'LF';
- }
- line = '';
- } else if ((matches = line.match(Comment))) {
- out.push('#' + matches[1] + '\n');
- state = 'NONE';
- line = '';
- } else if (LooksLikeCurl.test(line)) {
- parseCurlLine();
- } else if ((matches = line.match(SenseLine))) {
- out.push(matches[1] + ' /' + matches[2] + '\n');
- line = '';
- state = 'BODY';
- }
-
- // Nothing else matches, so output with a prefix of !!! for debugging purposes
- else {
- out.push('### ' + line);
- line = '';
- }
- }
-
- addBodyToOut();
- return out.join('').trim();
-}
diff --git a/src/plugins/console/public/lib/curl_parsing/curl_parsing.test.js b/src/plugins/console/public/lib/curl_parsing/curl_parsing.test.js
deleted file mode 100644
index 80a60cd259717..0000000000000
--- a/src/plugins/console/public/lib/curl_parsing/curl_parsing.test.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import _ from 'lodash';
-import { detectCURL, parseCURL } from './curl';
-import curlTests from './__fixtures__/curl_parsing.txt';
-
-describe('CURL', () => {
- const notCURLS = ['sldhfsljfhs', 's;kdjfsldkfj curl -XDELETE ""', '{ "hello": 1 }'];
- _.each(notCURLS, function (notCURL, i) {
- test('cURL Detection - broken strings ' + i, function () {
- expect(detectCURL(notCURL)).toEqual(false);
- });
- });
-
- curlTests.split(/^=+$/m).forEach(function (fixture) {
- if (fixture.trim() === '') {
- return;
- }
- fixture = fixture.split(/^-+$/m);
- const name = fixture[0].trim();
- const curlText = fixture[1];
- const response = fixture[2].trim();
-
- test('cURL Detection - ' + name, function () {
- expect(detectCURL(curlText)).toBe(true);
- const r = parseCURL(curlText);
- expect(r).toEqual(response);
- });
- });
-});
diff --git a/src/plugins/console/public/lib/kb/kb.test.js b/src/plugins/console/public/lib/kb/kb.test.js
index 70ea0ef33ae86..7560789718e58 100644
--- a/src/plugins/console/public/lib/kb/kb.test.js
+++ b/src/plugins/console/public/lib/kb/kb.test.js
@@ -10,7 +10,6 @@
import _ from 'lodash';
import { populateContext } from '../autocomplete/engine';
-import '../../application/models/sense_editor/sense_editor.test.mocks';
import * as kb from '.';
import { AutocompleteInfo, setAutocompleteInfo } from '../../services';
diff --git a/src/plugins/console/public/lib/row_parser.test.ts b/src/plugins/console/public/lib/row_parser.test.ts
deleted file mode 100644
index 869822b7bf055..0000000000000
--- a/src/plugins/console/public/lib/row_parser.test.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import '../application/models/legacy_core_editor/legacy_core_editor.test.mocks';
-
-import RowParser from './row_parser';
-import { create, MODE } from '../application/models';
-import type { SenseEditor } from '../application/models';
-import type { CoreEditor } from '../types';
-
-describe('RowParser', () => {
- let editor: SenseEditor | null;
- let parser: RowParser | null;
-
- beforeEach(function () {
- // Set up our document body
- document.body.innerHTML = ``;
- editor = create(document.getElementById('ConAppEditor')!);
- parser = new RowParser(editor.getCoreEditor() as CoreEditor);
- });
-
- afterEach(function () {
- editor?.getCoreEditor().destroy();
- editor = null;
- parser = null;
- });
-
- describe('getRowParseMode', () => {
- const forceRetokenize = false;
-
- it('should return MODE.BETWEEN_REQUESTS if line is empty', () => {
- editor?.getCoreEditor().setValue('', forceRetokenize);
- expect(parser?.getRowParseMode()).toBe(MODE.BETWEEN_REQUESTS);
- });
-
- it('should return MODE.BETWEEN_REQUESTS if line is a comment', () => {
- editor?.getCoreEditor().setValue('// comment', forceRetokenize);
- expect(parser?.getRowParseMode()).toBe(MODE.BETWEEN_REQUESTS);
- });
-
- it('should return MODE.REQUEST_START | MODE.REQUEST_END if line is a single line request', () => {
- editor?.getCoreEditor().setValue('GET _search', forceRetokenize);
- // eslint-disable-next-line no-bitwise
- expect(parser?.getRowParseMode()).toBe(MODE.REQUEST_START | MODE.REQUEST_END);
- });
-
- it('should return MODE.IN_REQUEST if line is a request with an opening curly brace', () => {
- editor?.getCoreEditor().setValue('{', forceRetokenize);
- expect(parser?.getRowParseMode()).toBe(MODE.IN_REQUEST);
- });
-
- it('should return MODE.MULTI_DOC_CUR_DOC_END | MODE.IN_REQUEST if line is a multi doc request with an opening curly brace', () => {
- editor?.getCoreEditor().setValue('GET _msearch\n{}\n{', forceRetokenize);
- const lineNumber = editor?.getCoreEditor().getLineCount()! - 1;
- expect(parser?.getRowParseMode(lineNumber)).toBe(
- // eslint-disable-next-line no-bitwise
- MODE.MULTI_DOC_CUR_DOC_END | MODE.IN_REQUEST
- );
- });
-
- it('should return MODE.MULTI_DOC_CUR_DOC_END | MODE.REQUEST_END if line is a multi doc request with a closing curly brace', () => {
- editor?.getCoreEditor().setValue('GET _msearch\n{}\n{"foo": 1}\n', forceRetokenize);
- const lineNumber = editor?.getCoreEditor().getLineCount()! - 1;
- expect(parser?.getRowParseMode(lineNumber)).toBe(
- // eslint-disable-next-line no-bitwise
- MODE.MULTI_DOC_CUR_DOC_END | MODE.REQUEST_END
- );
- });
-
- it('should return MODE.REQUEST_START | MODE.REQUEST_END if line is a request with variables', () => {
- editor?.getCoreEditor().setValue('GET /${exampleVariable}', forceRetokenize);
- // eslint-disable-next-line no-bitwise
- expect(parser?.getRowParseMode()).toBe(MODE.REQUEST_START | MODE.REQUEST_END);
- });
-
- it('should return MODE.REQUEST_START | MODE.REQUEST_END if a single request line ends with a closing curly brace', () => {
- editor?.getCoreEditor().setValue('DELETE /_bar/_baz%{test}', forceRetokenize);
- // eslint-disable-next-line no-bitwise
- expect(parser?.getRowParseMode()).toBe(MODE.REQUEST_START | MODE.REQUEST_END);
- });
-
- it('should return correct modes for multiple bulk requests', () => {
- editor
- ?.getCoreEditor()
- .setValue('POST _bulk\n{"index": {"_index": "test"}}\n{"foo": "bar"}\n', forceRetokenize);
- expect(parser?.getRowParseMode(0)).toBe(MODE.BETWEEN_REQUESTS);
- editor
- ?.getCoreEditor()
- .setValue('POST _bulk\n{"index": {"_index": "test"}}\n{"foo": "bar"}\n', forceRetokenize);
- const lineNumber = editor?.getCoreEditor().getLineCount()! - 1;
- expect(parser?.getRowParseMode(lineNumber)).toBe(
- // eslint-disable-next-line no-bitwise
- MODE.REQUEST_END | MODE.MULTI_DOC_CUR_DOC_END
- );
- });
- });
-});
diff --git a/src/plugins/console/public/lib/row_parser.ts b/src/plugins/console/public/lib/row_parser.ts
deleted file mode 100644
index 7078bb857d95b..0000000000000
--- a/src/plugins/console/public/lib/row_parser.ts
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { CoreEditor, Token } from '../types';
-import { TokenIterator } from './token_iterator';
-
-export const MODE = {
- REQUEST_START: 2,
- IN_REQUEST: 4,
- MULTI_DOC_CUR_DOC_END: 8,
- REQUEST_END: 16,
- BETWEEN_REQUESTS: 32,
-};
-
-// eslint-disable-next-line import/no-default-export
-export default class RowParser {
- constructor(private readonly editor: CoreEditor) {}
-
- MODE = MODE;
-
- getRowParseMode(lineNumber = this.editor.getCurrentPosition().lineNumber) {
- const linesCount = this.editor.getLineCount();
- if (lineNumber > linesCount || lineNumber < 1) {
- return MODE.BETWEEN_REQUESTS;
- }
- const mode = this.editor.getLineState(lineNumber);
-
- if (!mode) {
- return MODE.BETWEEN_REQUESTS;
- } // shouldn't really happen
- // If another "start" mode is added here because we want to allow for new language highlighting
- // please see https://github.com/elastic/kibana/pull/51446 for a discussion on why
- // should consider a different approach.
- if (mode !== 'start' && mode !== 'start-sql') {
- return MODE.IN_REQUEST;
- }
- let line = (this.editor.getLineValue(lineNumber) || '').trim();
-
- if (!line || line.startsWith('#') || line.startsWith('//') || line.startsWith('/*')) {
- return MODE.BETWEEN_REQUESTS;
- } // empty line or a comment waiting for a new req to start
-
- // Check for multi doc requests
- if (line.endsWith('}') && !this.isRequestLine(line)) {
- // check for a multi doc request must start a new json doc immediately after this one end.
- lineNumber++;
- if (lineNumber < linesCount + 1) {
- line = (this.editor.getLineValue(lineNumber) || '').trim();
- if (line.indexOf('{') === 0) {
- // next line is another doc in a multi doc
- // eslint-disable-next-line no-bitwise
- return MODE.MULTI_DOC_CUR_DOC_END | MODE.IN_REQUEST;
- }
- }
- // eslint-disable-next-line no-bitwise
- return MODE.REQUEST_END | MODE.MULTI_DOC_CUR_DOC_END; // end of request
- }
-
- // check for single line requests
- lineNumber++;
- if (lineNumber >= linesCount + 1) {
- // eslint-disable-next-line no-bitwise
- return MODE.REQUEST_START | MODE.REQUEST_END;
- }
- line = (this.editor.getLineValue(lineNumber) || '').trim();
- if (line.indexOf('{') !== 0) {
- // next line is another request
- // eslint-disable-next-line no-bitwise
- return MODE.REQUEST_START | MODE.REQUEST_END;
- }
-
- return MODE.REQUEST_START;
- }
-
- rowPredicate(lineNumber: number | undefined, editor: CoreEditor, value: number) {
- const mode = this.getRowParseMode(lineNumber);
- // eslint-disable-next-line no-bitwise
- return (mode & value) > 0;
- }
-
- isEndRequestRow(row?: number, _e?: CoreEditor) {
- const editor = _e || this.editor;
- return this.rowPredicate(row, editor, MODE.REQUEST_END);
- }
-
- isRequestEdge(row?: number, _e?: CoreEditor) {
- const editor = _e || this.editor;
- // eslint-disable-next-line no-bitwise
- return this.rowPredicate(row, editor, MODE.REQUEST_END | MODE.REQUEST_START);
- }
-
- isStartRequestRow(row?: number, _e?: CoreEditor) {
- const editor = _e || this.editor;
- return this.rowPredicate(row, editor, MODE.REQUEST_START);
- }
-
- isInBetweenRequestsRow(row?: number, _e?: CoreEditor) {
- const editor = _e || this.editor;
- return this.rowPredicate(row, editor, MODE.BETWEEN_REQUESTS);
- }
-
- isInRequestsRow(row?: number, _e?: CoreEditor) {
- const editor = _e || this.editor;
- return this.rowPredicate(row, editor, MODE.IN_REQUEST);
- }
-
- isMultiDocDocEndRow(row?: number, _e?: CoreEditor) {
- const editor = _e || this.editor;
- return this.rowPredicate(row, editor, MODE.MULTI_DOC_CUR_DOC_END);
- }
-
- isEmptyToken(tokenOrTokenIter: TokenIterator | Token | null) {
- const token =
- tokenOrTokenIter && (tokenOrTokenIter as TokenIterator).getCurrentToken
- ? (tokenOrTokenIter as TokenIterator).getCurrentToken()
- : tokenOrTokenIter;
- return !token || (token as Token).type === 'whitespace';
- }
-
- isUrlOrMethodToken(tokenOrTokenIter: TokenIterator | Token) {
- const t = (tokenOrTokenIter as TokenIterator)?.getCurrentToken() ?? (tokenOrTokenIter as Token);
- return t && t.type && (t.type === 'method' || t.type.indexOf('url') === 0);
- }
-
- nextNonEmptyToken(tokenIter: TokenIterator) {
- let t = tokenIter.stepForward();
- while (t && this.isEmptyToken(t)) {
- t = tokenIter.stepForward();
- }
- return t;
- }
-
- prevNonEmptyToken(tokenIter: TokenIterator) {
- let t = tokenIter.stepBackward();
- // empty rows return null token.
- while ((t || tokenIter.getCurrentPosition().lineNumber > 1) && this.isEmptyToken(t))
- t = tokenIter.stepBackward();
- return t;
- }
-
- isCommentToken(token: Token | null) {
- return (
- token &&
- token.type &&
- (token.type === 'comment.punctuation' ||
- token.type === 'comment.line' ||
- token.type === 'comment.block')
- );
- }
-
- isRequestLine(line: string) {
- const methods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'PATCH', 'OPTIONS'];
- return methods.some((m) => line.startsWith(m));
- }
-}
diff --git a/src/plugins/console/public/styles/_app.scss b/src/plugins/console/public/styles/_app.scss
index f42a94c3f786f..24be741d365b4 100644
--- a/src/plugins/console/public/styles/_app.scss
+++ b/src/plugins/console/public/styles/_app.scss
@@ -36,8 +36,6 @@
width: 100%;
display: flex;
flex: 0 0 auto;
-
- // Required on IE11 to render ace editor correctly after first input.
position: relative;
&__spinner {
@@ -55,46 +53,6 @@
height: 100%;
display: flex;
flex: 1 1 1px;
-
- .ace_badge {
- font-family: $euiFontFamily;
- font-size: $euiFontSizeXS;
- font-weight: $euiFontWeightMedium;
- line-height: $euiLineHeight;
- padding: 0 $euiSizeS;
- display: inline-block;
- text-decoration: none;
- border-radius: calc($euiBorderRadius / 2);
- white-space: nowrap;
- vertical-align: middle;
- cursor: default;
- max-width: 100%;
-
- &--success {
- background-color: $euiColorVis0_behindText;
- color: chooseLightOrDarkText($euiColorVis0_behindText);
- }
-
- &--warning {
- background-color: $euiColorVis5_behindText;
- color: chooseLightOrDarkText($euiColorVis5_behindText);
- }
-
- &--primary {
- background-color: $euiColorVis1_behindText;
- color: chooseLightOrDarkText($euiColorVis1_behindText);
- }
-
- &--default {
- background-color: $euiColorLightShade;
- color: chooseLightOrDarkText($euiColorLightShade);
- }
-
- &--danger {
- background-color: $euiColorVis9_behindText;
- color: chooseLightOrDarkText($euiColorVis9_behindText);
- }
- }
}
.conApp__editorContent,
@@ -145,17 +103,6 @@
margin-inline: 0;
}
-// SASSTODO: This component seems to not be used anymore?
-// Possibly replaced by the Ace version
-.conApp__autoComplete {
- position: absolute;
- left: -1000px;
- visibility: hidden;
- /* by pass any other element in ace and resize bar, but not modal popups */
- z-index: $euiZLevel1 + 2;
- margin-top: 22px;
-}
-
.conApp__requestProgressBarContainer {
position: relative;
z-index: $euiZLevel2;
diff --git a/src/plugins/console/public/types/core_editor.ts b/src/plugins/console/public/types/core_editor.ts
index aa9bdf21c1c94..8d5ab2a582226 100644
--- a/src/plugins/console/public/types/core_editor.ts
+++ b/src/plugins/console/public/types/core_editor.ts
@@ -7,7 +7,6 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
-import type { Editor } from 'brace';
import { ResultTerm } from '../lib/autocomplete/types';
import { TokensProvider } from './tokens_provider';
import { Token } from './token';
@@ -94,7 +93,7 @@ export enum LINE_MODE {
/**
* The CoreEditor is a component separate from the Editor implementation that provides Console
* app specific business logic. The CoreEditor is an interface to the lower-level editor implementation
- * being used which is usually vendor code such as Ace or Monaco.
+ * being used which is usually vendor code such as Monaco.
*/
export interface CoreEditor {
/**
@@ -260,7 +259,7 @@ export interface CoreEditor {
*/
registerKeyboardShortcut(opts: {
keys: string | { win?: string; mac?: string };
- fn: (editor: Editor) => void;
+ fn: (editor: any) => void;
name: string;
}): void;
diff --git a/src/plugins/console/tsconfig.json b/src/plugins/console/tsconfig.json
index 2b0f6127cd4af..02e4e7a9b7689 100644
--- a/src/plugins/console/tsconfig.json
+++ b/src/plugins/console/tsconfig.json
@@ -18,10 +18,8 @@
"@kbn/i18n-react",
"@kbn/shared-ux-utility",
"@kbn/core-http-browser",
- "@kbn/ace",
"@kbn/config-schema",
"@kbn/core-http-router-server-internal",
- "@kbn/web-worker-stub",
"@kbn/core-elasticsearch-server",
"@kbn/core-http-browser-mocks",
"@kbn/react-kibana-context-theme",
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 40096e431b883..3db116375ecbe 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -320,8 +320,6 @@
"coloring.dynamicColoring.rangeType.label": "Type de valeur",
"coloring.dynamicColoring.rangeType.number": "Numéro",
"coloring.dynamicColoring.rangeType.percent": "Pourcent",
- "console.autocomplete.addMethodMetaText": "méthode",
- "console.autocomplete.fieldsFetchingAnnotation": "La récupération des champs est en cours",
"console.autocompleteSuggestions.apiLabel": "API",
"console.autocompleteSuggestions.endpointLabel": "point de terminaison",
"console.autocompleteSuggestions.methodLabel": "méthode",
@@ -362,10 +360,6 @@
"console.loadingError.title": "Impossible de charger la console",
"console.notification.clearHistory": "Effacer l'historique",
"console.notification.disableSavingToHistory": "Désactiver l'enregistrement",
- "console.notification.error.couldNotSaveRequestTitle": "Impossible d'enregistrer la requête dans l'historique de la console.",
- "console.notification.error.historyQuotaReachedMessage": "L'historique des requêtes est arrivé à saturation. Effacez l'historique de la console ou désactivez l'enregistrement de nouvelles requêtes.",
- "console.notification.error.noRequestSelectedTitle": "Aucune requête sélectionnée. Sélectionnez une requête en positionnant le curseur dessus.",
- "console.notification.error.unknownErrorTitle": "Erreur de requête inconnue",
"console.pageHeading": "Console",
"console.requestInProgressBadgeText": "Requête en cours",
"console.requestOptions.autoIndentButtonLabel": "Appliquer les indentations",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 42388e901300e..67b07b28089c4 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -320,8 +320,6 @@
"coloring.dynamicColoring.rangeType.label": "値型",
"coloring.dynamicColoring.rangeType.number": "Number",
"coloring.dynamicColoring.rangeType.percent": "割合(%)",
- "console.autocomplete.addMethodMetaText": "メソド",
- "console.autocomplete.fieldsFetchingAnnotation": "フィールドの取得を実行しています",
"console.autocompleteSuggestions.apiLabel": "API",
"console.autocompleteSuggestions.endpointLabel": "エンドポイント",
"console.autocompleteSuggestions.methodLabel": "メソド",
@@ -362,10 +360,6 @@
"console.loadingError.title": "コンソールを読み込めません",
"console.notification.clearHistory": "履歴を消去",
"console.notification.disableSavingToHistory": "保存を無効にする",
- "console.notification.error.couldNotSaveRequestTitle": "リクエストをコンソール履歴に保存できませんでした。",
- "console.notification.error.historyQuotaReachedMessage": "リクエスト履歴が満杯です。コンソール履歴を消去するか、新しいリクエストの保存を無効にしてください。",
- "console.notification.error.noRequestSelectedTitle": "リクエストを選択していません。リクエストの中にカーソルを置いて選択します。",
- "console.notification.error.unknownErrorTitle": "不明なリクエストエラー",
"console.pageHeading": "コンソール",
"console.requestInProgressBadgeText": "リクエストが進行中",
"console.requestOptions.autoIndentButtonLabel": "インデントを適用",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 4d6476e6612b2..500063df288d5 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -319,8 +319,6 @@
"coloring.dynamicColoring.rangeType.label": "值类型",
"coloring.dynamicColoring.rangeType.number": "数字",
"coloring.dynamicColoring.rangeType.percent": "百分比",
- "console.autocomplete.addMethodMetaText": "方法",
- "console.autocomplete.fieldsFetchingAnnotation": "正在提取字段",
"console.autocompleteSuggestions.apiLabel": "API",
"console.autocompleteSuggestions.endpointLabel": "终端",
"console.autocompleteSuggestions.methodLabel": "方法",
@@ -361,10 +359,6 @@
"console.loadingError.title": "无法加载控制台",
"console.notification.clearHistory": "清除历史记录",
"console.notification.disableSavingToHistory": "禁止保存",
- "console.notification.error.couldNotSaveRequestTitle": "无法将请求保存到控制台历史记录。",
- "console.notification.error.historyQuotaReachedMessage": "请求历史记录已满。请清除控制台历史记录或禁止保存新的请求。",
- "console.notification.error.noRequestSelectedTitle": "未选择任何请求。将鼠标置于请求内即可选择。",
- "console.notification.error.unknownErrorTitle": "未知请求错误",
"console.pageHeading": "控制台",
"console.requestInProgressBadgeText": "进行中的请求",
"console.requestOptions.autoIndentButtonLabel": "应用行首缩进",