Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TSVB] Replaces EuiCodeEditor 👉 Monaco editor #100684

Merged
merged 27 commits into from
Jun 18, 2021
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bc993ee
Сhanged EuiCodeEditor to CodeEditor (monaco) at markdown_editor.js
Kuznietsov May 26, 2021
e37fcfb
Added css lang support for monaco-editor.
Kuznietsov May 26, 2021
d9ee143
Added .d.ts for css lang import directly from monaco.
Kuznietsov May 26, 2021
0787ffa
Moved handlebars_url language to the code_editor.
Kuznietsov May 26, 2021
2eb0ac8
Added merge for markdown_handlebars lang.
Kuznietsov May 26, 2021
713ea21
Changed to simple markdown syntax.
Kuznietsov May 26, 2021
f772f7a
Removed useless mergeConfig function.
Kuznietsov May 26, 2021
bb46bfc
Removed legacy import.
Kuznietsov May 26, 2021
670da6e
Refactor export from monaco-editor.
Kuznietsov May 26, 2021
b21a93a
Fixed 'Could not find a declaration file for module'
Kuznietsov May 27, 2021
47b3b22
Fixed tests.
Kuznietsov May 27, 2021
2a0aa06
Fixed typings errors.
Kuznietsov May 27, 2021
ea2bcf0
Added comment to typings.
Kuznietsov May 27, 2021
55f8e07
Fixed clearMarkdown for Monaco editor.
Kuznietsov May 27, 2021
3f1c0b9
Made changes based on suggestions.
Kuznietsov Jun 7, 2021
a42f32f
Merge branch 'master' into #99445
Kuznietsov Jun 7, 2021
e8cb769
Fixed types errors.
Kuznietsov Jun 7, 2021
8ddf8fe
Merge branch '#99445' of github.com:Kunzetsov/kibana into #99445
Kuznietsov Jun 7, 2021
b65dbf7
Fixed function tests types errors.
Kuznietsov Jun 7, 2021
aef246c
Fixes, based on nits.
Kuznietsov Jun 8, 2021
cdf60dd
Merge branch 'master' into #99445
kibanamachine Jun 8, 2021
1601e66
Merge branch 'master' into #99445
kibanamachine Jun 8, 2021
1b72e92
Merge branch 'master' into #99445
kibanamachine Jun 10, 2021
5437e26
Merge branch 'master' into #99445
kibanamachine Jun 14, 2021
5398a81
Merge branch 'master' into #99445
kibanamachine Jun 16, 2021
c2448cd
Merge branch 'master' into #99445
kibanamachine Jun 18, 2021
ed05215
Fixes based on nits.
Kuznietsov Jun 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/kbn-monaco/src/esql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
* Side Public License, v 1.
*/

import { LangModule as LangModuleType } from '../types';
import { ID } from './constants';
import { lexerRules } from './lexer_rules';

export const EsqlLang = { ID, lexerRules };
export const EsqlLang = { ID, lexerRules } as LangModuleType;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit; could we update this to:

Suggested change
export const EsqlLang = { ID, lexerRules } as LangModuleType;
export const EsqlLang: LangModuleType = { ID, lexerRules };

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, not a problem. I was using the style of @kbn/monaco )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

21 changes: 21 additions & 0 deletions packages/kbn-monaco/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/
import { monaco } from './monaco_imports';
import { LangModule as LangModuleType } from './types';

function registerLanguage(language: LangModuleType) {
const { ID, lexerRules, languageConfiguration } = language;

monaco.languages.register({ id: ID });
monaco.languages.setMonarchTokensProvider(ID, lexerRules);
if (languageConfiguration) {
monaco.languages.setLanguageConfiguration(ID, languageConfiguration);
}
}

export { registerLanguage };
10 changes: 8 additions & 2 deletions packages/kbn-monaco/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ import './register_globals';
export { monaco } from './monaco_imports';
export { XJsonLang } from './xjson';
export { PainlessLang, PainlessContext, PainlessAutocompleteField } from './painless';

/* eslint-disable-next-line @kbn/eslint/module_migration */
import * as BarePluginApi from 'monaco-editor/esm/vs/editor/editor.api';
export { BarePluginApi };

import { registerLanguage } from './helpers';
import {
LangModule as LangModuleType,
CompleteLangModule as CompleteLangModuleType,
} from './types';

export { BarePluginApi, registerLanguage, LangModuleType, CompleteLangModuleType };
3 changes: 2 additions & 1 deletion packages/kbn-monaco/src/painless/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
import { ID } from './constants';
import { lexerRules, languageConfiguration } from './lexer_rules';
import { getSuggestionProvider, getSyntaxErrors } from './language';
import { CompleteLangModule as CompleteLangModuleType } from '../types';

export const PainlessLang = {
ID,
getSuggestionProvider,
lexerRules,
languageConfiguration,
getSyntaxErrors,
};
} as CompleteLangModuleType;

export { PainlessContext, PainlessAutocompleteField } from './types';
13 changes: 5 additions & 8 deletions packages/kbn-monaco/src/register_globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { XJsonLang } from './xjson';
import { PainlessLang } from './painless';
import { EsqlLang } from './esql';
import { monaco } from './monaco_imports';
import { registerLanguage } from './helpers';

// @ts-ignore
import xJsonWorkerSrc from '!!raw-loader!../../target_web/xjson.editor.worker.js';
// @ts-ignore
Expand All @@ -20,14 +22,9 @@ import painlessWorkerSrc from '!!raw-loader!../../target_web/painless.editor.wor
/**
* Register languages and lexer rules
*/
monaco.languages.register({ id: XJsonLang.ID });
monaco.languages.setMonarchTokensProvider(XJsonLang.ID, XJsonLang.lexerRules);
monaco.languages.setLanguageConfiguration(XJsonLang.ID, XJsonLang.languageConfiguration);
monaco.languages.register({ id: PainlessLang.ID });
monaco.languages.setMonarchTokensProvider(PainlessLang.ID, PainlessLang.lexerRules);
monaco.languages.setLanguageConfiguration(PainlessLang.ID, PainlessLang.languageConfiguration);
monaco.languages.register({ id: EsqlLang.ID });
monaco.languages.setMonarchTokensProvider(EsqlLang.ID, EsqlLang.lexerRules);
registerLanguage(XJsonLang);
registerLanguage(PainlessLang);
registerLanguage(EsqlLang);

/**
* Create web workers by language ID
Expand Down
22 changes: 22 additions & 0 deletions packages/kbn-monaco/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/
import { monaco } from './monaco_imports';

export interface LangModule {
ID: string;
lexerRules: monaco.languages.IMonarchLanguage;
languageConfiguration?: monaco.languages.LanguageConfiguration;
getSuggestionProvider?: Function;
getSyntaxErrors?: Function;
}

export interface CompleteLangModule extends LangModule {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this type needed? I assume it fixes a TS error related to the PainlessLang, since that's the only place it's being used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First I've started fixing those errors, but then I've recognized, that from the engineering perspective, in the future it can appear more complex configurations for languages, you'll want to support (as we have one already).

Copy link
Contributor Author

@Kuznietsov Kuznietsov Jun 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LangModuleType will be used for simple or predefined languages, which already exist in monaco.
CompleteLangModuleType will be used for complex, self-written languages.

languageConfiguration: monaco.languages.LanguageConfiguration;
getSuggestionProvider: Function;
getSyntaxErrors: Function;
}
3 changes: 2 additions & 1 deletion packages/kbn-monaco/src/xjson/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
import './language';
import { ID } from './constants';
import { lexerRules, languageConfiguration } from './lexer_rules';
import { LangModule as LangModuleType } from '../types';

export const XJsonLang = { ID, lexerRules, languageConfiguration };
export const XJsonLang = { ID, lexerRules, languageConfiguration } as LangModuleType;
3 changes: 3 additions & 0 deletions src/plugins/kibana_react/public/code_editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import darkTheme from '@elastic/eui/dist/eui_theme_dark.json';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
import { useUiSetting } from '../ui_settings';
import { Props } from './code_editor';
import './register_languages';

export * from './languages';

const LazyBaseEditor = React.lazy(() => import('./code_editor'));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
* Side Public License, v 1.
*/

export const LANG = 'handlebars_url';
export const LANG = 'css';
12 changes: 12 additions & 0 deletions src/plugins/kibana_react/public/code_editor/languages/css/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if someone already asked this; what is the reason for having these language definitions live here and not in the @kbn/monaco package (with painless etc)?

Copy link
Contributor Author

@Kuznietsov Kuznietsov Jun 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it is a good idea to put some custom languages, required only in kibana plugins, to the core package. If the code owners will say, that it is a good idea, I'll do it)

Copy link
Contributor Author

@Kuznietsov Kuznietsov Jun 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jloleysens, what do you think about it? Is there any reasons for storing custom languages in the global package?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, as far as I understand it, the languages defined in kbn/monaco are intended for use in plugins, or at least that plugins are the biggest consumers of that functionality. Could you help me understand the distinction with, for e.g., Handlebars vs Painless?

IMO it would be best to have a single place where languages are created and registered for easy reuse and discoverability - similar to @poffdeluxe comment.

Is part of the concern JS bundle size?

With the current kbn/monaco package plugins can't cherry-pick/declare languages they want to use and there is no good way to audit what languages are being used where (searching I suppose). But with monaco language definitions I don't think there is a lot of JS being loaded typically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Painless, xjson and Esql are specific for elastic stack. But markdown, css and handlebars are common and they are just imported from monaco. I was thinking about that languages, which require syntax implementation, need to be located at kbn/monaco, all other - at plugins. But if somebody want to move languages, please, feel free to do it) I'm sorry, right now I'm working on the other task.

* 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 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 or the Server
* Side Public License, v 1.
*/
import { LangModuleType } from '@kbn/monaco';
import { lexerRules, languageConfiguration } from './language';
import { LANG } from './constants';

export const Lang: LangModuleType = { ID: LANG, lexerRules, languageConfiguration };
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

/* eslint-disable @kbn/eslint/module_migration */
import { conf, language } from 'monaco-editor/esm/vs/basic-languages/css/css';

export { conf as languageConfiguration, language as lexerRules };
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

export const LANG = 'handlebars';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

import { LangModuleType } from '@kbn/monaco';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not getting much information from the word "Module" in this name. I'm used to thinking of modules in the node_modules sense, but not able to translate that meaning to this context. Is there a context that gives it meaning here?

This type seems to be a configuration object, specific to registering languages with our monaco package. I think a better name would be one that hints at that meaning, maybe MonacoLanguageConfig?

Copy link
Contributor Author

@Kuznietsov Kuznietsov Jun 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you can see, all languages in @kbn/monaco and in plugins/kibana-react/public/code-editor are represented as libraries, which encapsulate the complexity of configuring the language for monaco. They provide only the common interface (contract, if you want) to use. They are represented as libraries. That is a definition of the module, as I think (not node_modules, but the definition of usual module in javascript and modular programming).

What about MonacoLanguageConfig, I would prefer such a name, if there would be the only configuration for languages, but it also provides functions to getting errors and autocompletion in some languages. And it would confuse users (programmers), because in the terminology of monaco - config is just a part of configuring the language.

import { languageConfiguration, lexerRules } from './language';
import { LANG } from './constants';

export const Lang: LangModuleType = { ID: LANG, languageConfiguration, lexerRules };
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import { monaco } from '@kbn/monaco';

export const conf: monaco.languages.LanguageConfiguration = {
export const languageConfiguration: monaco.languages.LanguageConfiguration = {
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,

comments: {
Expand Down Expand Up @@ -42,7 +42,7 @@ export const conf: monaco.languages.LanguageConfiguration = {
],
};

export const language: monaco.languages.IMonarchLanguage = {
export const lexerRules: monaco.languages.IMonarchLanguage = {
// Set defaultToken to invalid to see what you do not tokenize yet.
defaultToken: 'invalid',
tokenPostfix: '',
Expand Down
13 changes: 13 additions & 0 deletions src/plugins/kibana_react/public/code_editor/languages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

import { Lang as CssLang } from './css';
import { Lang as HandlebarsLang } from './handlebars';
import { Lang as MarkdownLang } from './markdown';

export { CssLang, HandlebarsLang, MarkdownLang };
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

export const LANG = 'markdown';
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/
import { LangModuleType } from '@kbn/monaco';
import { languageConfiguration, lexerRules } from './language';
import { LANG } from './constants';

export const Lang: LangModuleType = { ID: LANG, languageConfiguration, lexerRules };
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

/* eslint-disable @kbn/eslint/module_migration */
import { conf, language } from 'monaco-editor/esm/vs/basic-languages/markdown/markdown';

export { conf as languageConfiguration, language as lexerRules };
13 changes: 13 additions & 0 deletions src/plugins/kibana_react/public/code_editor/register_languages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/
import { registerLanguage } from '@kbn/monaco';
import { CssLang, HandlebarsLang, MarkdownLang } from './languages';

registerLanguage(CssLang);
registerLanguage(HandlebarsLang);
registerLanguage(MarkdownLang);
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,10 @@
import * as React from 'react';
import { monaco } from '@kbn/monaco';
import { Props as CodeEditorProps } from '../code_editor/code_editor';
import { CodeEditor } from '../code_editor';
import { LANG } from './constants';
import { language, conf } from './language';
import { CodeEditor, HandlebarsLang } from '../code_editor';

import './styles.scss';

monaco.languages.register({
id: LANG,
});
monaco.languages.setMonarchTokensProvider(LANG, language);
monaco.languages.setLanguageConfiguration(LANG, conf);

export interface UrlTemplateEditorVariable {
label: string;
title?: string;
Expand Down Expand Up @@ -74,7 +66,7 @@ export const UrlTemplateEditor: React.FC<UrlTemplateEditorProps> = ({
return;
}

const { dispose } = monaco.languages.registerCompletionItemProvider(LANG, {
const { dispose } = monaco.languages.registerCompletionItemProvider(HandlebarsLang.ID, {
triggerCharacters: ['{', '/', '?', '&', '='],
provideCompletionItems(model, position, context, token) {
const { lineNumber } = position;
Expand Down Expand Up @@ -132,7 +124,7 @@ export const UrlTemplateEditor: React.FC<UrlTemplateEditorProps> = ({
return (
<div className={'urlTemplateEditor__container'} onKeyDown={handleKeyDown}>
<Editor
languageId={LANG}
languageId={HandlebarsLang.ID}
height={height}
value={value}
onChange={onChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import React, { Component } from 'react';
import { createTickFormatter } from './lib/tick_formatter';
import { convertSeriesToVars } from './lib/convert_series_to_vars';
import _ from 'lodash';
import 'brace/mode/markdown';
import 'brace/theme/github';
import { CodeEditor, MarkdownLang } from '../../../../kibana_react/public';

import { EuiText, EuiCodeBlock, EuiSpacer, EuiTitle, EuiCodeEditor } from '@elastic/eui';
import { EuiText, EuiCodeBlock, EuiSpacer, EuiTitle } from '@elastic/eui';

import { FormattedMessage } from '@kbn/i18n/react';

Expand Down Expand Up @@ -101,14 +100,13 @@ export class MarkdownEditor extends Component {
return (
<div className="tvbMarkdownEditor">
<div className="tvbMarkdownEditor__editor">
<EuiCodeEditor
onLoad={this.handleOnLoad}
mode="markdown"
theme="github"
width="100%"
height="100%"
name={`ace-${model.id}`}
setOptions={{ wrap: true, fontSize: '14px' }}
<CodeEditor
editorDidMount={this.handleOnLoad}
languageId={MarkdownLang.ID}
options={{
fontSize: '14px',
wordWrap: 'on',
}}
value={model.markdown}
onChange={this.handleChange}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
EuiSpacer,
EuiTitle,
EuiHorizontalRule,
EuiCodeEditor,
} from '@elastic/eui';
// @ts-expect-error
import less from 'less/lib/less-browser';
Expand All @@ -43,6 +42,7 @@ import { getDefaultQueryLanguage } from '../lib/get_default_query_language';
import { VisDataContext } from '../../contexts/vis_data_context';
import { PanelConfigProps, PANEL_CONFIG_TABS } from './types';
import { TimeseriesVisParams } from '../../../types';
import { CodeEditor, CssLang } from '../../../../../kibana_react/public';

const lessC = less(window, { env: 'production' });

Expand Down Expand Up @@ -281,12 +281,10 @@ export class MarkdownPanelConfig extends Component<
</span>
</EuiTitle>
<EuiSpacer size="s" />
<EuiCodeEditor
mode="less"
theme="github"
width="100%"
name={`ace-css-${model.id}`}
setOptions={{ fontSize: '14px' }}
<CodeEditor
height="500px"
languageId={CssLang.ID}
options={{ fontSize: 14 }}
value={model.markdown_less ?? ''}
onChange={this.handleCSSChange}
/>
Expand Down
Loading