Skip to content

Commit

Permalink
Update Kibana code editor dependencies (#171720)
Browse files Browse the repository at this point in the history
## Summary

This PR started out as an attempt to resolve
#166559; which it does, the
appropriate colours for the message prompt displayed when an edit
attempt on read only content is made in the code editor for both dark
and light mode are now set;

 ### Light mode
<img width="412" alt="Screenshot 2023-11-22 at 11 30 17"
src="https://github.com/elastic/kibana/assets/7893459/8675dd9f-b413-4098-a903-7ac63dc367fb">

### Dark mode
<img width="843" alt="Screenshot 2023-11-22 at 11 29 31"
src="https://github.com/elastic/kibana/assets/7893459/64fd39e0-d5dd-4556-b6ca-75ba8fc55c94">

#### Noteworthy**

- See https://code.visualstudio.com/api/references/theme-color for more
clarification on the style definitions added to this PR
- There's also been accommodation made for consumers of the code editor
to provide their own custom message through the prop `readOnlyMessage`.
- That been said it's worth pointing out that this PR updates
react-monaco-editor and monaco-editor packages to their latest version,
primarily because the functionality that provides support to provide
customization for the providing a color scheme that would support in our
use case for setting colors for dark mode and light mode appropriately,
shipped in version 0.40.0 of monaco editor, also for react-monaco-editor
prior to it's current latest the pinned version of monaco editor was
0.38.0.
- Monaco-yaml is also updated in the PR, matching the change in
expectation of the underlying monaco-editor api.
~- Updates to the packages referenced above, in turn caused the
installed version of prettier to be updated to the latest minor version
2.8.8. This change caused some lint changes to the project files where
parentheses were added to types with Index Access on another type
created using the typeof operator (more context
[here](prettier/prettier#14990)), for this
reason I've opted to lockdown prettier version, so that this PR only
contains the changes required for updating the code editor. A subsequent
PR will be created to revert the package lockdown so that PR contains
only the lint changes that will occur.~

### Checklist
<!--
Delete any items that are not applicable to this PR. -->

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
<!-- - [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios -->
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
<!-- - [ ] Any UI touched in this PR does not create any new axe
failures (run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)


### Risk Matrix

Delete this section if it is not applicable to this PR.

Before closing this PR, invite QA, stakeholders, and other developers to
identify risks that should be tested prior to the change/feature
release.

When forming the risk matrix, consider some of the following examples
and how they may potentially impact the change:

| Risk | Probability | Severity | Mitigation/Notes |

|---------------------------|-------------|----------|-------------------------|
| Multiple Spaces&mdash;unexpected behavior in non-default Kibana Space.
| Low | High | Integration tests will verify that all features are still
supported in non-default Kibana Space and when user switches between
spaces. |
| Multiple nodes&mdash;Elasticsearch polling might have race conditions
when multiple Kibana nodes are polling for the same tasks. | High | Low
| Tasks are idempotent, so executing them multiple times will not result
in logical error, but will degrade performance. To test for this case we
add plenty of unit tests around this logic and document manual testing
procedure. |
| Code should gracefully handle cases when feature X or plugin Y are
disabled. | Medium | High | Unit tests will verify that any feature flag
or plugin combination still results in our service operational. |
| [See more potential risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) |


### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
-->

---------

Co-authored-by: Aleh Zasypkin <[email protected]>
Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
3 people authored Jan 25, 2024
1 parent c5d4ffd commit b25407e
Show file tree
Hide file tree
Showing 43 changed files with 426 additions and 178 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class ExampleCurrencyFormat extends FieldFormat {
return new Intl.NumberFormat(undefined, {
style: 'currency',
currency: this.param('currency'),
currencyDisplay: 'narrowSymbol',
}).format(val);
};
}
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1012,8 +1012,8 @@
"moment": "^2.29.4",
"moment-duration-format": "^2.3.2",
"moment-timezone": "^0.5.43",
"monaco-editor": "^0.24.0",
"monaco-yaml": "3.2.1",
"monaco-editor": "^0.44.0",
"monaco-yaml": "^5.1.0",
"mustache": "^2.3.2",
"node-fetch": "^2.6.7",
"node-forge": "^1.3.1",
Expand Down Expand Up @@ -1057,7 +1057,7 @@
"react-is": "^17.0.2",
"react-markdown": "^6.0.3",
"react-moment-proptypes": "^1.7.0",
"react-monaco-editor": "^0.41.2",
"react-monaco-editor": "^0.54.0",
"react-popper-tooltip": "^3.1.1",
"react-redux": "^7.2.8",
"react-resizable": "^3.0.4",
Expand Down Expand Up @@ -1139,12 +1139,13 @@
"@babel/generator": "^7.23.6",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/parser": "^7.23.6",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-transform-class-properties": "^7.23.3",
"@babel/plugin-transform-numeric-separator": "^7.23.4",
"@babel/plugin-transform-runtime": "^7.23.6",
"@babel/preset-env": "^7.23.6",
"@babel/preset-react": "^7.23.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-babel-preset/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ NPM_MODULE_EXTRA_FILES = [
]

RUNTIME_DEPS = [
"@npm//@babel/plugin-proposal-class-properties",
"@npm//@babel/plugin-transform-class-properties",
"@npm//@babel/plugin-proposal-export-namespace-from",
"@npm//@babel/plugin-proposal-nullish-coalescing-operator",
"@npm//@babel/plugin-proposal-optional-chaining",
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-babel-preset/common_preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module.exports = () => ({
// TECHNICALLY stage 2, but for all intents and purposes it's stage 3
//
// See https://github.com/babel/proposals/issues/12 for progress
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-transform-class-properties'),

// Optional Chaining proposal is stage 4 (https://github.com/tc39/proposal-optional-chaining)
// Need this since we are using TypeScript 3.7+
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-monaco/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ webpack_cli(
data = SRCS + SHARED_DEPS + [
"//:.browserslistrc",
"//packages/kbn-babel-preset",
"@npm//terser-webpack-plugin",
"@npm//@babel/runtime",
"@npm//babel-loader",
"@npm//raw-loader",
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-monaco/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type { ESQLCallbacks } from './src/esql';
export * from './src/painless';
/* eslint-disable-next-line @kbn/eslint/module_migration */
import * as BarePluginApi from 'monaco-editor/esm/vs/editor/editor.api';
export { YAML_LANG_ID, configureMonacoYamlSchema } from './src/yaml';

import { registerLanguage } from './src/helpers';

Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-monaco/src/__jest__/jest.mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const createMockModel = (ID: string) => {
uri: '',
id: 'mockModel',
value: '',
getModeId: () => ID,
getLanguageId: () => ID,
changeContentListeners: [],
setValue(newValue) {
this.value = newValue;
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-monaco/src/__jest__/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface MockIModel {
id: string;
value: string;
changeContentListeners: Array<() => void>;
getModeId: () => string;
getLanguageId: () => string;
setValue: (value: string) => void;
getValue: () => string;
onDidChangeContent: (handler: () => void) => void;
Expand Down
4 changes: 2 additions & 2 deletions packages/kbn-monaco/src/common/diagnostics_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export class DiagnosticsAdapter {
const onModelAdd = (model: monaco.editor.IModel): void => {
let handle: any;

if (model.getModeId() === this.langId) {
if (model.getLanguageId() === this.langId) {
model.onDidChangeContent(() => {
// Do not validate if the language ID has changed
if (model.getModeId() !== this.langId) {
if (model.getLanguageId() !== this.langId) {
return;
}

Expand Down
18 changes: 9 additions & 9 deletions packages/kbn-monaco/src/monaco_imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
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/base/browser/defaultWorkerFactory';

import 'monaco-editor/esm/vs/editor/browser/controller/coreCommands.js';
import 'monaco-editor/esm/vs/editor/browser/coreCommands.js';
import 'monaco-editor/esm/vs/editor/browser/widget/codeEditorWidget.js';

import 'monaco-editor/esm/vs/editor/contrib/wordOperations/wordOperations.js'; // Needed for word-wise char navigation
import 'monaco-editor/esm/vs/editor/contrib/linesOperations/linesOperations.js'; // Needed for enabling shortcuts of removing/joining/moving lines
import 'monaco-editor/esm/vs/editor/contrib/folding/folding.js'; // Needed for folding
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-editor/esm/vs/editor/contrib/bracketMatching/bracketMatching.js'; // Needed for brackets matching highlight
import 'monaco-editor/esm/vs/editor/contrib/wordOperations/browser/wordOperations.js'; // Needed for word-wise char navigation
import 'monaco-editor/esm/vs/editor/contrib/linesOperations/browser/linesOperations.js'; // Needed for enabling shortcuts of removing/joining/moving lines
import 'monaco-editor/esm/vs/editor/contrib/folding/browser/folding.js'; // Needed for folding
import 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggestController.js'; // Needed for suggestions
import 'monaco-editor/esm/vs/editor/contrib/hover/browser/hover.js'; // Needed for hover
import 'monaco-editor/esm/vs/editor/contrib/parameterHints/browser/parameterHints.js'; // Needed for signature
import 'monaco-editor/esm/vs/editor/contrib/bracketMatching/browser/bracketMatching.js'; // Needed for brackets matching highlight

import 'monaco-editor/esm/vs/language/json/monaco.contribution.js';
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js'; // Needed for basic javascript support
Expand Down
8 changes: 4 additions & 4 deletions packages/kbn-monaco/src/register_globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { PainlessLang } from './painless';
import { SQLLang } from './sql';
import { monaco } from './monaco_imports';
import { ESQL_THEME_ID, ESQLLang, buildESQlTheme } from './esql';
import { YAML_LANG_ID } from './yaml';
import { registerLanguage, registerTheme } from './helpers';

export const DEFAULT_WORKER_ID = 'default';
Expand All @@ -19,7 +20,7 @@ const langSpecificWorkerIds = [
PainlessLang.ID,
ESQLLang.ID,
monaco.languages.json.jsonDefaults.languageId,
'yaml',
YAML_LANG_ID,
];

/**
Expand All @@ -37,9 +38,8 @@ registerTheme(ESQL_THEME_ID, buildESQlTheme());

const monacoBundleDir = (window as any).__kbnPublicPath__?.['kbn-monaco'];

// @ts-ignore
window.MonacoEnvironment = {
// needed for functional tests so that we can get value from 'editor'
// @ts-expect-error needed for functional tests so that we can get value from 'editor'
monaco,
getWorkerUrl: monacoBundleDir
? (_: string, languageId: string) => {
Expand All @@ -48,5 +48,5 @@ window.MonacoEnvironment = {
: DEFAULT_WORKER_ID;
return `${monacoBundleDir}${workerId}.editor.worker.js`;
}
: () => undefined,
: () => '',
};
2 changes: 1 addition & 1 deletion packages/kbn-monaco/src/xjson/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ monaco.languages.onLanguage(ID, async () => {
};

const onModelAdd = (model: monaco.editor.IModel) => {
if (model.getModeId() !== ID) {
if (model.getLanguageId() !== ID) {
return;
}

Expand Down
9 changes: 9 additions & 0 deletions packages/kbn-monaco/src/yaml/constants.ts
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 ID = 'yaml';
27 changes: 27 additions & 0 deletions packages/kbn-monaco/src/yaml/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 { type MonacoYamlOptions } from 'monaco-yaml';
import { monaco } from '../monaco_imports';

export { ID as YAML_LANG_ID } from './constants';

const monacoYamlDefaultOptions: MonacoYamlOptions = {
completion: true,
hover: true,
validate: true,
};

export const configureMonacoYamlSchema = async (schemas: MonacoYamlOptions['schemas']) => {
const { configureMonacoYaml } = await import(/* webpackChunkName: "monaco-yaml" */ 'monaco-yaml');

return configureMonacoYaml(monaco, {
...monacoYamlDefaultOptions,
schemas,
});
};
9 changes: 9 additions & 0 deletions packages/kbn-monaco/src/yaml/worker/yaml.worker.ts
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.
*/

import 'monaco-yaml/yaml.worker.js';
48 changes: 42 additions & 6 deletions packages/kbn-monaco/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,32 @@ const getWorkerEntry = (language) => {
return 'monaco-editor/esm/vs/editor/editor.worker.js';
case 'json':
return 'monaco-editor/esm/vs/language/json/json.worker.js';
case 'yaml':
return 'monaco-yaml/lib/esm/yaml.worker.js';
default:
return path.resolve(__dirname, 'src', language, 'worker', `${language}.worker.ts`);
}
};

const getWorkerConfig = (language) => ({
/**
* @param {string[]} languages - list of supported languages to build workers for
* @returns {import('webpack').Configuration}
*/
const workerConfig = (languages) => ({
mode: process.env.NODE_ENV || 'development',
entry: getWorkerEntry(language),
entry: languages.reduce((entries, language) => {
entries[language] = getWorkerEntry(language);
return entries;
}, {}),
devtool: process.env.NODE_ENV === 'production' ? false : '#cheap-source-map',
output: {
path: path.resolve(__dirname, 'target_workers'),
filename: `${language}.editor.worker.js`,
filename: ({ chunk }) => `${chunk.name}.editor.worker.js`,
},
resolve: {
extensions: ['.js', '.ts', '.tsx'],
alias: {
// swap default umd import for the esm one provided in vscode-uri package
'vscode-uri$': require.resolve('vscode-uri').replace(/\/umd\/index.js/, '/esm/index.mjs'),
},
},
stats: 'errors-only',
module: {
Expand All @@ -47,8 +56,35 @@ const getWorkerConfig = (language) => ({
},
},
},
{
/**
* further process the modules exported by monaco-editor and monaco-yaml
* because their exports leverage some none-standard language APIs at this time.
*/
test: /(monaco-editor\/esm\/vs\/language|monaco-yaml|vscode-uri)\/.*m?(t|j)sx?$/,
use: {
loader: 'babel-loader',
options: {
babelrc: false,
envName: process.env.NODE_ENV || 'development',
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
},
},
},
],
},
optimization: {
minimizer: [
(compiler) => {
const TerserPlugin = require('terser-webpack-plugin');
new TerserPlugin({
// exclude this file from being processed by terser,
// because attempts at tree shaking actually botches up the file
exclude: /monaco-editor[\\/]esm[\\/]vs[\\/]base[\\/]common[\\/]map.js/,
}).apply(compiler);
},
],
},
});

module.exports = ['default', 'json', 'painless', 'xjson', 'esql', 'yaml'].map(getWorkerConfig);
module.exports = workerConfig(['default', 'json', 'painless', 'xjson', 'esql', 'yaml']);
4 changes: 2 additions & 2 deletions packages/kbn-test/jest-preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ module.exports = {

// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
transformIgnorePatterns: [
// ignore all node_modules except monaco-editor and react-monaco-editor which requires babel transforms to handle dynamic import()
// ignore all node_modules except monaco-editor, monaco-yaml and react-monaco-editor which requires babel transforms to handle dynamic import()
// since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842)
'[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|monaco-yaml|vscode-languageserver-types|react-monaco-editor|d3-interpolate|d3-color|langchain|langsmith|@cfworker|gpt-tokenizer))[/\\\\].+\\.js$',
'[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|monaco-yaml|monaco-languageserver-types|monaco-marker-data-provider|monaco-worker-manager|vscode-languageserver-types|react-monaco-editor|d3-interpolate|d3-color|langchain|langsmith|@cfworker|gpt-tokenizer))[/\\\\].+\\.js$',
'packages/kbn-pm/dist/index.js',
'[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/[/\\\\].+\\.js$',
'[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/util/[/\\\\].+\\.js$',
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-ui-shared-deps-src/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ webpack_cli(
"@npm//babel-loader",
"@npm//css-loader",
"@npm//url-loader",
"@npm//@babel/plugin-transform-numeric-separator",
"//packages/kbn-ui-shared-deps-npm",
"//packages/kbn-babel-register",
"//packages/kbn-babel-preset",
Expand Down
17 changes: 17 additions & 0 deletions packages/kbn-ui-shared-deps-src/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@ module.exports = {
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
},
},
{
/**
* further process the modules exported by both monaco-editor and monaco-yaml, because;
* 1). they both use non-standard language APIs
* 2). monaco-yaml exports it's src as is see, https://www.npmjs.com/package/monaco-yaml#does-it-work-without-a-bundler
*/
test: /(monaco-editor\/esm\/vs\/|monaco-languageserver-types|monaco-marker-data-provider|monaco-worker-manager).*(t|j)sx?$/,
use: {
loader: 'babel-loader',
options: {
babelrc: false,
envName: process.env.NODE_ENV || 'development',
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
plugins: [require.resolve('@babel/plugin-transform-numeric-separator')],
},
},
},
],
},

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b25407e

Please sign in to comment.