add monaco to kbn/ui-shared-deps and load required features for all uses (#58075)

* add monaco to kbn/ui-shared-deps and load required features for all uses

* forgot to save a change

* remove unused imports

* include a cache buster to counteract issue #58077

* include monaco.ts in ts project
This commit is contained in:
Spencer 2020-02-20 12:58:42 -07:00 committed by GitHub
parent 3bd639dd68
commit 4aedf2b75b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 128 additions and 90 deletions

View file

@ -17,6 +17,7 @@
* under the License.
*/
// cache buster - https://github.com/elastic/kibana/issues/58077 - 1
export { OptimizerConfig } from './optimizer';
export * from './run_optimizer';
export * from './log_optimizer_state';

View file

@ -40,6 +40,8 @@ export const ReactDom = require('react-dom');
export const ReactIntl = require('react-intl');
export const ReactRouter = require('react-router'); // eslint-disable-line
export const ReactRouterDom = require('react-router-dom');
export const Monaco = require('./monaco.ts');
export const MonacoBare = require('monaco-editor/esm/vs/editor/editor.api');
// load timezone data into moment-timezone
Moment.tz.load(require('moment-timezone/data/packed/latest.json'));

View file

@ -41,4 +41,7 @@ exports.externals = {
'react-intl': '__kbnSharedDeps__.ReactIntl',
'react-router': '__kbnSharedDeps__.ReactRouter',
'react-router-dom': '__kbnSharedDeps__.ReactRouterDom',
'@kbn/ui-shared-deps/monaco': '__kbnSharedDeps__.Monaco',
// this is how plugins/consumers from npm load monaco
'monaco-editor/esm/vs/editor/editor.api': '__kbnSharedDeps__.MonacoBare',
};

View file

@ -0,0 +1,32 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import 'monaco-editor/esm/vs/base/common/worker/simpleWorker';
import 'monaco-editor/esm/vs/base/worker/defaultWorkerFactory';
import 'monaco-editor/esm/vs/editor/browser/controller/coreCommands.js';
import 'monaco-editor/esm/vs/editor/browser/widget/codeEditorWidget.js';
import 'monaco-editor/esm/vs/editor/contrib/suggest/suggestController.js'; // Needed for suggestions
import 'monaco-editor/esm/vs/editor/contrib/hover/hover.js'; // Needed for hover
import 'monaco-editor/esm/vs/editor/contrib/parameterHints/parameterHints.js'; // Needed for signature
export { monaco };

View file

@ -12,6 +12,7 @@
"@elastic/charts": "^17.0.2",
"abortcontroller-polyfill": "^1.4.0",
"@elastic/eui": "19.0.0",
"@kbn/babel-preset": "1.0.0",
"@kbn/dev-utils": "1.0.0",
"@kbn/i18n": "1.0.0",
"@yarnpkg/lockfile": "^1.1.0",

View file

@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"include": [
"index.d.ts"
"index.d.ts",
"monaco.ts"
]
}

View file

@ -59,6 +59,17 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
include: [require.resolve('./monaco.ts')],
use: [
{
loader: 'babel-loader',
options: {
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
},
},
],
},
],
},

View file

@ -20,7 +20,7 @@
import React, { useEffect, useCallback, useRef, useMemo } from 'react';
import { EuiFormLabel } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
import { monaco } from '@kbn/ui-shared-deps/monaco';
import { CodeEditor, useKibana } from '../../../../../plugins/kibana_react/public';
import { suggest, getSuggestion } from './timelion_expression_input_helpers';
@ -31,7 +31,7 @@ import {
} from '../../../../../plugins/timelion/common/types';
const LANGUAGE_ID = 'timelion_expression';
monacoEditor.languages.register({ id: LANGUAGE_ID });
monaco.languages.register({ id: LANGUAGE_ID });
interface TimelionExpressionInputProps {
value: string;
@ -44,10 +44,10 @@ function TimelionExpressionInput({ value, setValue }: TimelionExpressionInputPro
const argValueSuggestions = useMemo(getArgValueSuggestions, []);
const provideCompletionItems = useCallback(
async (model: monacoEditor.editor.ITextModel, position: monacoEditor.Position) => {
async (model: monaco.editor.ITextModel, position: monaco.Position) => {
const text = model.getValue();
const wordUntil = model.getWordUntilPosition(position);
const wordRange = new monacoEditor.Range(
const wordRange = new monaco.Range(
position.lineNumber,
wordUntil.startColumn,
position.lineNumber,
@ -75,7 +75,7 @@ function TimelionExpressionInput({ value, setValue }: TimelionExpressionInputPro
);
const provideHover = useCallback(
async (model: monacoEditor.editor.ITextModel, position: monacoEditor.Position) => {
async (model: monaco.editor.ITextModel, position: monaco.Position) => {
const suggestions = await suggest(
model.getValue(),
functionList.current,

View file

@ -19,7 +19,7 @@
import { get, startsWith } from 'lodash';
import { i18n } from '@kbn/i18n';
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
import { monaco } from '@kbn/ui-shared-deps/monaco';
import { Parser } from 'pegjs';
@ -215,14 +215,13 @@ export async function suggest(
export function getSuggestion(
suggestion: ITimelionFunction | TimelionFunctionArgs,
type: SUGGESTION_TYPE,
range: monacoEditor.Range
): monacoEditor.languages.CompletionItem {
let kind: monacoEditor.languages.CompletionItemKind =
monacoEditor.languages.CompletionItemKind.Method;
range: monaco.Range
): monaco.languages.CompletionItem {
let kind: monaco.languages.CompletionItemKind = monaco.languages.CompletionItemKind.Method;
let insertText: string = suggestion.name;
let insertTextRules: monacoEditor.languages.CompletionItem['insertTextRules'];
let insertTextRules: monaco.languages.CompletionItem['insertTextRules'];
let detail: string = '';
let command: monacoEditor.languages.CompletionItem['command'];
let command: monaco.languages.CompletionItem['command'];
switch (type) {
case SUGGESTION_TYPE.ARGUMENTS:
@ -230,7 +229,7 @@ export function getSuggestion(
title: 'Trigger Suggestion Dialog',
id: 'editor.action.triggerSuggest',
};
kind = monacoEditor.languages.CompletionItemKind.Property;
kind = monaco.languages.CompletionItemKind.Property;
insertText = `${insertText}=`;
detail = `${i18n.translate(
'timelion.expressionSuggestions.argument.description.acceptsText',
@ -245,9 +244,9 @@ export function getSuggestion(
title: 'Trigger Suggestion Dialog',
id: 'editor.action.triggerSuggest',
};
kind = monacoEditor.languages.CompletionItemKind.Function;
kind = monaco.languages.CompletionItemKind.Function;
insertText = `${insertText}($0)`;
insertTextRules = monacoEditor.languages.CompletionItemInsertTextRule.InsertAsSnippet;
insertTextRules = monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet;
detail = `(${
(suggestion as ITimelionFunction).chainable
? i18n.translate('timelion.expressionSuggestions.func.description.chainableHelpText', {
@ -270,7 +269,7 @@ export function getSuggestion(
title: 'Trigger Suggestion Dialog',
id: 'editor.action.triggerSuggest',
};
kind = monacoEditor.languages.CompletionItemKind.Property;
kind = monaco.languages.CompletionItemKind.Property;
detail = suggestion.help || '';
break;

View file

@ -19,13 +19,13 @@
import React from 'react';
import { CodeEditor } from './code_editor';
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
import { monaco } from '@kbn/ui-shared-deps/monaco';
import { shallow } from 'enzyme';
import 'monaco-editor/esm/vs/basic-languages/html/html.contribution.js';
// A sample language definition with a few example tokens
const simpleLogLang: monacoEditor.languages.IMonarchLanguage = {
const simpleLogLang: monaco.languages.IMonarchLanguage = {
tokenizer: {
root: [
[/\[error.*/, 'constant'],
@ -36,8 +36,8 @@ const simpleLogLang: monacoEditor.languages.IMonarchLanguage = {
},
};
monacoEditor.languages.register({ id: 'loglang' });
monacoEditor.languages.setMonarchTokensProvider('loglang', simpleLogLang);
monaco.languages.register({ id: 'loglang' });
monaco.languages.setMonarchTokensProvider('loglang', simpleLogLang);
const logs = `
[Sun Mar 7 20:54:27 2004] [notice] [client xx.xx.xx.xx] This is a notice!
@ -55,23 +55,22 @@ test('is rendered', () => {
test('editor mount setup', () => {
const suggestionProvider = {
provideCompletionItems: (
model: monacoEditor.editor.ITextModel,
position: monacoEditor.Position
) => ({ suggestions: [] }),
provideCompletionItems: (model: monaco.editor.ITextModel, position: monaco.Position) => ({
suggestions: [],
}),
};
const signatureProvider = {
provideSignatureHelp: () => ({ signatures: [], activeParameter: 0, activeSignature: 0 }),
};
const hoverProvider = {
provideHover: (model: monacoEditor.editor.ITextModel, position: monacoEditor.Position) => ({
provideHover: (model: monaco.editor.ITextModel, position: monaco.Position) => ({
contents: [],
}),
};
const editorWillMount = jest.fn();
monacoEditor.languages.onLanguage = jest.fn((languageId, func) => {
monaco.languages.onLanguage = jest.fn((languageId, func) => {
expect(languageId).toBe('loglang');
// Call the function immediately so we can see our providers
@ -79,11 +78,11 @@ test('editor mount setup', () => {
func();
}) as any;
monacoEditor.languages.registerCompletionItemProvider = jest.fn();
monacoEditor.languages.registerSignatureHelpProvider = jest.fn();
monacoEditor.languages.registerHoverProvider = jest.fn();
monaco.languages.registerCompletionItemProvider = jest.fn();
monaco.languages.registerSignatureHelpProvider = jest.fn();
monaco.languages.registerHoverProvider = jest.fn();
monacoEditor.editor.defineTheme = jest.fn();
monaco.editor.defineTheme = jest.fn();
const wrapper = shallow(
<CodeEditor
@ -98,21 +97,17 @@ test('editor mount setup', () => {
);
const instance = wrapper.instance() as CodeEditor;
instance._editorWillMount(monacoEditor);
instance._editorWillMount(monaco);
// Verify our mount callback will be called
expect(editorWillMount.mock.calls.length).toBe(1);
// Verify our theme will be setup
expect((monacoEditor.editor.defineTheme as jest.Mock).mock.calls.length).toBe(1);
expect((monaco.editor.defineTheme as jest.Mock).mock.calls.length).toBe(1);
// Verify our language features have been registered
expect((monacoEditor.languages.onLanguage as jest.Mock).mock.calls.length).toBe(1);
expect(
(monacoEditor.languages.registerCompletionItemProvider as jest.Mock).mock.calls.length
).toBe(1);
expect(
(monacoEditor.languages.registerSignatureHelpProvider as jest.Mock).mock.calls.length
).toBe(1);
expect((monacoEditor.languages.registerHoverProvider as jest.Mock).mock.calls.length).toBe(1);
expect((monaco.languages.onLanguage as jest.Mock).mock.calls.length).toBe(1);
expect((monaco.languages.registerCompletionItemProvider as jest.Mock).mock.calls.length).toBe(1);
expect((monaco.languages.registerSignatureHelpProvider as jest.Mock).mock.calls.length).toBe(1);
expect((monaco.languages.registerHoverProvider as jest.Mock).mock.calls.length).toBe(1);
});

View file

@ -19,18 +19,9 @@
import React from 'react';
import ReactResizeDetector from 'react-resize-detector';
import MonacoEditor, { EditorDidMount, EditorWillMount } from 'react-monaco-editor';
import MonacoEditor from 'react-monaco-editor';
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
import 'monaco-editor/esm/vs/base/common/worker/simpleWorker';
import 'monaco-editor/esm/vs/base/worker/defaultWorkerFactory';
import 'monaco-editor/esm/vs/editor/browser/controller/coreCommands.js';
import 'monaco-editor/esm/vs/editor/browser/widget/codeEditorWidget.js';
import 'monaco-editor/esm/vs/editor/contrib/suggest/suggestController.js'; // Needed for suggestions
import 'monaco-editor/esm/vs/editor/contrib/hover/hover.js'; // Needed for hover
import 'monaco-editor/esm/vs/editor/contrib/parameterHints/parameterHints.js'; // Needed for signature
import { monaco } from '@kbn/ui-shared-deps/monaco';
import { LIGHT_THEME, DARK_THEME } from './editor_theme';
@ -55,50 +46,50 @@ export interface Props {
* Documentation of options can be found here:
* https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditorconstructionoptions.html
*/
options?: monacoEditor.editor.IEditorConstructionOptions;
options?: monaco.editor.IEditorConstructionOptions;
/**
* Suggestion provider for autocompletion
* Documentation for the provider can be found here:
* https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.completionitemprovider.html
*/
suggestionProvider?: monacoEditor.languages.CompletionItemProvider;
suggestionProvider?: monaco.languages.CompletionItemProvider;
/**
* Signature provider for function parameter info
* Documentation for the provider can be found here:
* https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.signaturehelpprovider.html
*/
signatureProvider?: monacoEditor.languages.SignatureHelpProvider;
signatureProvider?: monaco.languages.SignatureHelpProvider;
/**
* Hover provider for hover documentation
* Documentation for the provider can be found here:
* https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.hoverprovider.html
*/
hoverProvider?: monacoEditor.languages.HoverProvider;
hoverProvider?: monaco.languages.HoverProvider;
/**
* Language config provider for bracket
* Documentation for the provider can be found here:
* https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.languageconfiguration.html
*/
languageConfiguration?: monacoEditor.languages.LanguageConfiguration;
languageConfiguration?: monaco.languages.LanguageConfiguration;
/**
* Function called before the editor is mounted in the view
*/
editorWillMount?: EditorWillMount;
editorWillMount?: () => void;
/**
* Function called before the editor is mounted in the view
* and completely replaces the setup behavior called by the component
*/
overrideEditorWillMount?: EditorWillMount;
overrideEditorWillMount?: () => void;
/**
* Function called after the editor is mounted in the view
*/
editorDidMount?: EditorDidMount;
editorDidMount?: (editor: monaco.editor.IStandaloneCodeEditor) => void;
/**
* Should the editor use the dark theme
@ -107,16 +98,20 @@ export interface Props {
}
export class CodeEditor extends React.Component<Props, {}> {
_editor: monacoEditor.editor.IStandaloneCodeEditor | null = null;
_editor: monaco.editor.IStandaloneCodeEditor | null = null;
_editorWillMount = (__monaco: unknown) => {
if (__monaco !== monaco) {
throw new Error('react-monaco-editor is using a different version of monaco');
}
_editorWillMount = (monaco: typeof monacoEditor) => {
if (this.props.overrideEditorWillMount) {
this.props.overrideEditorWillMount(monaco);
this.props.overrideEditorWillMount();
return;
}
if (this.props.editorWillMount) {
this.props.editorWillMount(monaco);
this.props.editorWillMount();
}
monaco.languages.onLanguage(this.props.languageId, () => {
@ -150,14 +145,15 @@ export class CodeEditor extends React.Component<Props, {}> {
monaco.editor.defineTheme('euiColors', this.props.useDarkTheme ? DARK_THEME : LIGHT_THEME);
};
_editorDidMount = (
editor: monacoEditor.editor.IStandaloneCodeEditor,
monaco: typeof monacoEditor
) => {
_editorDidMount = (editor: monaco.editor.IStandaloneCodeEditor, __monaco: unknown) => {
if (__monaco !== monaco) {
throw new Error('react-monaco-editor is using a different version of monaco');
}
this._editor = editor;
if (this.props.editorDidMount) {
this.props.editorDidMount(editor, monaco);
this.props.editorDidMount(editor);
}
};

View file

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
import { monaco } from '@kbn/ui-shared-deps/monaco';
import darkTheme from '@elastic/eui/dist/eui_theme_dark.json';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
@ -27,7 +27,7 @@ import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
export function createTheme(
euiTheme: typeof darkTheme | typeof lightTheme,
selectionBackgroundColor: string
): monacoEditor.editor.IStandaloneThemeData {
): monaco.editor.IStandaloneThemeData {
return {
base: 'vs',
inherit: true,

View file

@ -7,7 +7,7 @@
import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react';
import React from 'react';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { monaco } from '@kbn/ui-shared-deps/monaco';
import { ExpressionInput } from '../expression_input';
import { language, LANGUAGE_ID } from '../../../lib/monaco_language_def';

View file

@ -8,7 +8,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { EuiFormRow } from '@elastic/eui';
import { debounce } from 'lodash';
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
import { monaco } from '@kbn/ui-shared-deps/monaco';
import { ExpressionFunction } from '../../../../../../../src/plugins/expressions';
import { CodeEditor } from '../../../../../../../src/plugins/kibana_react/public';
import {
@ -46,7 +46,7 @@ export class ExpressionInput extends React.Component<Props> {
onChange: PropTypes.func.isRequired,
};
editor: monacoEditor.editor.IStandaloneCodeEditor | null;
editor: monaco.editor.IStandaloneCodeEditor | null;
undoHistory: string[];
redoHistory: string[];
@ -114,9 +114,9 @@ export class ExpressionInput extends React.Component<Props> {
};
provideSuggestions = (
model: monacoEditor.editor.ITextModel,
position: monacoEditor.Position,
context: monacoEditor.languages.CompletionContext
model: monaco.editor.ITextModel,
position: monaco.Position,
context: monaco.languages.CompletionContext
) => {
const text = model.getValue();
const textRange = model.getFullModelRange();
@ -128,13 +128,13 @@ export class ExpressionInput extends React.Component<Props> {
endColumn: textRange.endColumn,
});
let wordRange: monacoEditor.Range;
let wordRange: monaco.Range;
let aSuggestions;
if (context.triggerCharacter === '{') {
const wordUntil = model.getWordAtPosition(position.delta(0, -3));
if (wordUntil) {
wordRange = new monacoEditor.Range(
wordRange = new monaco.Range(
position.lineNumber,
position.column,
position.lineNumber,
@ -151,7 +151,7 @@ export class ExpressionInput extends React.Component<Props> {
}
} else {
const wordUntil = model.getWordUntilPosition(position);
wordRange = new monacoEditor.Range(
wordRange = new monaco.Range(
position.lineNumber,
wordUntil.startColumn,
position.lineNumber,
@ -173,7 +173,7 @@ export class ExpressionInput extends React.Component<Props> {
if (s.type === 'argument') {
return {
label: s.argDef.name,
kind: monacoEditor.languages.CompletionItemKind.Variable,
kind: monaco.languages.CompletionItemKind.Variable,
documentation: { value: getArgReferenceStr(s.argDef), isTrusted: true },
insertText: s.text,
command: {
@ -186,7 +186,7 @@ export class ExpressionInput extends React.Component<Props> {
} else if (s.type === 'value') {
return {
label: s.text,
kind: monacoEditor.languages.CompletionItemKind.Value,
kind: monaco.languages.CompletionItemKind.Value,
insertText: s.text,
command: {
title: 'Trigger Suggestion Dialog',
@ -198,7 +198,7 @@ export class ExpressionInput extends React.Component<Props> {
} else {
return {
label: s.fnDef.name,
kind: monacoEditor.languages.CompletionItemKind.Function,
kind: monaco.languages.CompletionItemKind.Function,
documentation: {
value: getFunctionReferenceStr(s.fnDef),
isTrusted: true,
@ -219,7 +219,7 @@ export class ExpressionInput extends React.Component<Props> {
};
};
providerHover = (model: monacoEditor.editor.ITextModel, position: monacoEditor.Position) => {
providerHover = (model: monaco.editor.ITextModel, position: monaco.Position) => {
const text = model.getValue();
const word = model.getWordAtPosition(position);
@ -248,7 +248,7 @@ export class ExpressionInput extends React.Component<Props> {
const startPos = model.getPositionAt(argStart);
const endPos = model.getPositionAt(argEnd);
const argRange = new monacoEditor.Range(
const argRange = new monaco.Range(
startPos.lineNumber,
startPos.column,
endPos.lineNumber,
@ -275,10 +275,7 @@ export class ExpressionInput extends React.Component<Props> {
};
};
editorDidMount = (
editor: monacoEditor.editor.IStandaloneCodeEditor,
monaco: typeof monacoEditor
) => {
editorDidMount = (editor: monaco.editor.IStandaloneCodeEditor) => {
// Updating tab size for the editor
const model = editor.getModel();
if (model) {

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { monaco } from '@kbn/ui-shared-deps/monaco';
import { npSetup } from 'ui/new_platform';
export const LANGUAGE_ID = 'canvas-expression';