mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Panel Inspect: use monaco for json display (#25251)
This commit is contained in:
parent
dcd5752086
commit
1a711e7df0
@ -1,4 +1,4 @@
|
|||||||
const esModule = '@iconscout/react-unicons';
|
const esModule = '@iconscout/react-unicons|monaco-editor/esm/vs';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
verbose: false,
|
verbose: false,
|
||||||
@ -16,5 +16,6 @@ module.exports = {
|
|||||||
globals: { 'ts-jest': { isolatedModules: true } },
|
globals: { 'ts-jest': { isolatedModules: true } },
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'\\.svg': '<rootDir>/public/test/mocks/svg.ts',
|
'\\.svg': '<rootDir>/public/test/mocks/svg.ts',
|
||||||
|
'\\.css': '<rootDir>/public/test/mocks/style.ts',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -163,7 +163,8 @@
|
|||||||
"mini-css-extract-plugin": "0.9.0",
|
"mini-css-extract-plugin": "0.9.0",
|
||||||
"mocha": "7.0.1",
|
"mocha": "7.0.1",
|
||||||
"module-alias": "2.2.2",
|
"module-alias": "2.2.2",
|
||||||
"monaco-editor": "0.15.6",
|
"monaco-editor": "0.20.0",
|
||||||
|
"monaco-editor-webpack-plugin": "1.9.0",
|
||||||
"mutationobserver-shim": "0.3.3",
|
"mutationobserver-shim": "0.3.3",
|
||||||
"ngtemplate-loader": "2.0.1",
|
"ngtemplate-loader": "2.0.1",
|
||||||
"node-sass": "4.13.1",
|
"node-sass": "4.13.1",
|
||||||
|
@ -180,6 +180,8 @@ const getBaseWebpackConfig: WebpackConfigurationGetter = async options => {
|
|||||||
'@grafana/ui',
|
'@grafana/ui',
|
||||||
'@grafana/runtime',
|
'@grafana/runtime',
|
||||||
'@grafana/data',
|
'@grafana/data',
|
||||||
|
'monaco-editor',
|
||||||
|
'react-monaco-editor',
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
(context, request, callback) => {
|
(context, request, callback) => {
|
||||||
const prefix = 'grafana/';
|
const prefix = 'grafana/';
|
||||||
|
@ -78,12 +78,36 @@ module.exports = ({ config, mode }) => {
|
|||||||
|
|
||||||
config.optimization = {
|
config.optimization = {
|
||||||
nodeEnv: 'production',
|
nodeEnv: 'production',
|
||||||
|
moduleIds: 'hashed',
|
||||||
|
runtimeChunk: 'single',
|
||||||
|
splitChunks: {
|
||||||
|
chunks: 'all',
|
||||||
|
minChunks: 1,
|
||||||
|
cacheGroups: {
|
||||||
|
monaco: {
|
||||||
|
test: /[\\/]node_modules[\\/](monaco-editor)[\\/].*[jt]sx?$/,
|
||||||
|
chunks: 'initial',
|
||||||
|
priority: 20,
|
||||||
|
enforce: true,
|
||||||
|
},
|
||||||
|
vendors: {
|
||||||
|
test: /[\\/]node_modules[\\/].*[jt]sx?$/,
|
||||||
|
chunks: 'initial',
|
||||||
|
priority: -10,
|
||||||
|
reuseExistingChunk: true,
|
||||||
|
enforce: true,
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
priority: -20,
|
||||||
|
chunks: 'all',
|
||||||
|
test: /.*[jt]sx?$/,
|
||||||
|
reuseExistingChunk: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
minimize: true,
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new TerserPlugin({
|
new TerserPlugin({ cache: false, parallel: false, sourceMap: false, exclude: /monaco/ }),
|
||||||
cache: false,
|
|
||||||
parallel: false,
|
|
||||||
sourceMap: false,
|
|
||||||
}),
|
|
||||||
new OptimizeCSSAssetsPlugin({}),
|
new OptimizeCSSAssetsPlugin({}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
"immutable": "3.8.2",
|
"immutable": "3.8.2",
|
||||||
"jquery": "3.5.1",
|
"jquery": "3.5.1",
|
||||||
"lodash": "4.17.15",
|
"lodash": "4.17.15",
|
||||||
|
"monaco-editor": "0.20.0",
|
||||||
|
"react-monaco-editor": "0.36.0",
|
||||||
"moment": "2.24.0",
|
"moment": "2.24.0",
|
||||||
"papaparse": "4.6.3",
|
"papaparse": "4.6.3",
|
||||||
"rc-cascader": "1.0.1",
|
"rc-cascader": "1.0.1",
|
||||||
|
@ -25,7 +25,16 @@ const buildCjsPackage = ({ env }) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
external: ['react', 'react-dom', '@grafana/data', 'moment', '@grafana/e2e-selectors'],
|
external: [
|
||||||
|
'react',
|
||||||
|
'react-dom',
|
||||||
|
'@grafana/data',
|
||||||
|
'@grafana/e2e-selectors',
|
||||||
|
'moment',
|
||||||
|
'monaco-editor', // Monaco should not be used directly
|
||||||
|
'monaco-editor/esm/vs/editor/editor.api', // Monaco should not be used directly
|
||||||
|
'react-monaco-editor',
|
||||||
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
commonjs({
|
commonjs({
|
||||||
include: /node_modules/,
|
include: /node_modules/,
|
||||||
|
8
packages/grafana-ui/src/components/Monaco/CodeEditor.mdx
Normal file
8
packages/grafana-ui/src/components/Monaco/CodeEditor.mdx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||||
|
import { CodeEditor } from './CodeEditor';
|
||||||
|
|
||||||
|
<Meta title="MDX|CodeEditor" component={CodeEditor} />
|
||||||
|
|
||||||
|
# CodeEditor
|
||||||
|
|
||||||
|
Monaco Code editor
|
@ -0,0 +1,42 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { text } from '@storybook/addon-knobs';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||||
|
import mdx from './CodeEditor.mdx';
|
||||||
|
import CodeEditor from './CodeEditor';
|
||||||
|
|
||||||
|
const getKnobs = () => {
|
||||||
|
return {
|
||||||
|
text: text('Body', 'SELECT * FROM table LIMIT 10'),
|
||||||
|
language: text('Language', 'sql'),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'CodeEditor',
|
||||||
|
component: CodeEditor,
|
||||||
|
decorators: [withCenteredStory],
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
page: mdx,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const basic = () => {
|
||||||
|
const { text, language } = getKnobs();
|
||||||
|
return (
|
||||||
|
<CodeEditor
|
||||||
|
value={text}
|
||||||
|
language={language}
|
||||||
|
onBlur={(text: string) => {
|
||||||
|
console.log('Blur: ', text);
|
||||||
|
action('code blur')(text);
|
||||||
|
}}
|
||||||
|
onSave={(text: string) => {
|
||||||
|
console.log('Save: ', text);
|
||||||
|
action('code saved')(text);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
92
packages/grafana-ui/src/components/Monaco/CodeEditor.tsx
Normal file
92
packages/grafana-ui/src/components/Monaco/CodeEditor.tsx
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { withTheme } from '../../themes';
|
||||||
|
import { Themeable } from '../../types';
|
||||||
|
import { KeyCode, editor, KeyMod } from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
|
import ReactMonaco from 'react-monaco-editor';
|
||||||
|
|
||||||
|
export interface CodeEditorProps {
|
||||||
|
value: string;
|
||||||
|
language: string;
|
||||||
|
width?: number | string;
|
||||||
|
height?: number | string;
|
||||||
|
|
||||||
|
readOnly?: boolean;
|
||||||
|
showMiniMap?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback after the editor has mounted that gives you raw access to monaco
|
||||||
|
*
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
onEditorDidMount?: (editor: editor.IStandaloneCodeEditor) => void;
|
||||||
|
|
||||||
|
/** Handler to be performed when editor is blurred */
|
||||||
|
onBlur?: CodeEditorChangeHandler;
|
||||||
|
|
||||||
|
/** Handler to be performed when Cmd/Ctrl+S is pressed */
|
||||||
|
onSave?: CodeEditorChangeHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = CodeEditorProps & Themeable;
|
||||||
|
|
||||||
|
class UnthemedCodeEditor extends React.PureComponent<Props> {
|
||||||
|
getEditorValue = () => '';
|
||||||
|
|
||||||
|
onBlur = () => {
|
||||||
|
const { onBlur } = this.props;
|
||||||
|
if (onBlur) {
|
||||||
|
onBlur(this.getEditorValue());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
editorDidMount = (editor: editor.IStandaloneCodeEditor) => {
|
||||||
|
const { onSave, onEditorDidMount } = this.props;
|
||||||
|
|
||||||
|
this.getEditorValue = () => editor.getValue();
|
||||||
|
|
||||||
|
if (onSave) {
|
||||||
|
editor.addCommand(KeyMod.CtrlCmd | KeyCode.KEY_S, () => {
|
||||||
|
onSave(this.getEditorValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onEditorDidMount) {
|
||||||
|
onEditorDidMount(editor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { theme, language, width, height, showMiniMap, readOnly } = this.props;
|
||||||
|
const value = this.props.value ?? '';
|
||||||
|
const longText = value.length > 100;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div onBlur={this.onBlur}>
|
||||||
|
<ReactMonaco
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
language={language}
|
||||||
|
theme={theme.isDark ? 'vs-dark' : 'vs-light'}
|
||||||
|
value={value}
|
||||||
|
options={{
|
||||||
|
wordWrap: 'off',
|
||||||
|
codeLens: false, // not included in the bundle
|
||||||
|
minimap: {
|
||||||
|
enabled: longText && showMiniMap,
|
||||||
|
renderCharacters: false,
|
||||||
|
},
|
||||||
|
readOnly,
|
||||||
|
lineNumbersMinChars: 4,
|
||||||
|
lineDecorationsWidth: 0,
|
||||||
|
overviewRulerBorder: false,
|
||||||
|
automaticLayout: true,
|
||||||
|
}}
|
||||||
|
editorDidMount={this.editorDidMount}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CodeEditorChangeHandler = (value: string) => void;
|
||||||
|
export default withTheme(UnthemedCodeEditor);
|
29
packages/grafana-ui/src/components/Monaco/CodeEditorLazy.tsx
Normal file
29
packages/grafana-ui/src/components/Monaco/CodeEditorLazy.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useAsyncDependency } from '../../utils/useAsyncDependency';
|
||||||
|
import { ErrorWithStack, LoadingPlaceholder } from '..';
|
||||||
|
import { CodeEditorProps } from './CodeEditor';
|
||||||
|
|
||||||
|
export type CodeEditorChangeHandler = (value: string) => void;
|
||||||
|
|
||||||
|
export const CodeEditor: React.FC<CodeEditorProps> = props => {
|
||||||
|
const { loading, error, dependency } = useAsyncDependency(
|
||||||
|
import(/* webpackChunkName: "code-editor" */ './CodeEditor')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <LoadingPlaceholder text={'Loading...'} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<ErrorWithStack
|
||||||
|
title="Code editor failed to load"
|
||||||
|
error={error}
|
||||||
|
errorInfo={{ componentStack: error?.stack || '' }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CodeEditor = dependency.default;
|
||||||
|
return <CodeEditor {...props} />;
|
||||||
|
};
|
@ -34,6 +34,7 @@ export { FilterPill } from './FilterPill/FilterPill';
|
|||||||
|
|
||||||
export { ConfirmModal } from './ConfirmModal/ConfirmModal';
|
export { ConfirmModal } from './ConfirmModal/ConfirmModal';
|
||||||
export { QueryField } from './QueryField/QueryField';
|
export { QueryField } from './QueryField/QueryField';
|
||||||
|
export { CodeEditor } from './Monaco/CodeEditorLazy';
|
||||||
|
|
||||||
// TODO: namespace
|
// TODO: namespace
|
||||||
export { Modal } from './Modal/Modal';
|
export { Modal } from './Modal/Modal';
|
||||||
|
13
packages/grafana-ui/src/utils/useAsyncDependency.ts
Normal file
13
packages/grafana-ui/src/utils/useAsyncDependency.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { useAsync } from 'react-use';
|
||||||
|
|
||||||
|
// Allows simple dynamic imports in the components
|
||||||
|
export const useAsyncDependency = (importStatement: Promise<any>) => {
|
||||||
|
const state = useAsync(async () => {
|
||||||
|
return await importStatement;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dependency: state.value,
|
||||||
|
};
|
||||||
|
};
|
@ -1,9 +1,9 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { chain } from 'lodash';
|
import { chain } from 'lodash';
|
||||||
import { AppEvents, PanelData, SelectableValue } from '@grafana/data';
|
import { AppEvents, PanelData, SelectableValue } from '@grafana/data';
|
||||||
import { Button, ClipboardButton, Field, JSONFormatter, Select, TextArea } from '@grafana/ui';
|
import { Button, CodeEditor, Field, Select } from '@grafana/ui';
|
||||||
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { appEvents } from 'app/core/core';
|
import { appEvents } from 'app/core/core';
|
||||||
import { DashboardModel, PanelModel } from '../../state';
|
import { DashboardModel, PanelModel } from '../../state';
|
||||||
import { getPanelInspectorStyles } from './styles';
|
import { getPanelInspectorStyles } from './styles';
|
||||||
@ -49,20 +49,18 @@ export class InspectJSONTab extends PureComponent<Props, State> {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
show: ShowContent.PanelJSON,
|
show: ShowContent.PanelJSON,
|
||||||
text: getSaveModelJSON(props.panel),
|
text: getPrettyJSON(props.panel.getSaveModel()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelectChanged = (item: SelectableValue<ShowContent>) => {
|
onSelectChanged = (item: SelectableValue<ShowContent>) => {
|
||||||
let text = '';
|
const show = this.getJSONObject(item.value);
|
||||||
if (item.value === ShowContent.PanelJSON) {
|
const text = getPrettyJSON(show);
|
||||||
text = getSaveModelJSON(this.props.panel);
|
|
||||||
}
|
|
||||||
this.setState({ text, show: item.value });
|
this.setState({ text, show: item.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
onTextChanged = (e: React.FormEvent<HTMLTextAreaElement>) => {
|
// Called onBlur
|
||||||
const text = e.currentTarget.value;
|
onTextChanged = (text: string) => {
|
||||||
this.setState({ text });
|
this.setState({ text });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,17 +91,7 @@ export class InspectJSONTab extends PureComponent<Props, State> {
|
|||||||
return this.props.panel.getSaveModel();
|
return this.props.panel.getSaveModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
return { note: 'Unknown Object', show };
|
return { note: `Unknown Object: ${show}` };
|
||||||
};
|
|
||||||
|
|
||||||
getClipboardText = () => {
|
|
||||||
const { show } = this.state;
|
|
||||||
const obj = this.getJSONObject(show);
|
|
||||||
return JSON.stringify(obj, null, 2);
|
|
||||||
};
|
|
||||||
|
|
||||||
onClipboardCopied = () => {
|
|
||||||
appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onApplyPanelModel = () => {
|
onApplyPanelModel = () => {
|
||||||
@ -126,12 +114,6 @@ export class InspectJSONTab extends PureComponent<Props, State> {
|
|||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
renderPanelJSON(styles: any) {
|
|
||||||
return (
|
|
||||||
<TextArea spellCheck={false} value={this.state.text} onChange={this.onTextChanged} className={styles.editor} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dashboard } = this.props;
|
const { dashboard } = this.props;
|
||||||
const { show } = this.state;
|
const { show } = this.state;
|
||||||
@ -146,14 +128,6 @@ export class InspectJSONTab extends PureComponent<Props, State> {
|
|||||||
<Field label="Select source" className="flex-grow-1">
|
<Field label="Select source" className="flex-grow-1">
|
||||||
<Select options={options} value={selected} onChange={this.onSelectChanged} />
|
<Select options={options} value={selected} onChange={this.onSelectChanged} />
|
||||||
</Field>
|
</Field>
|
||||||
<ClipboardButton
|
|
||||||
variant="secondary"
|
|
||||||
className={styles.toolbarItem}
|
|
||||||
getText={this.getClipboardText}
|
|
||||||
onClipboardCopy={this.onClipboardCopied}
|
|
||||||
>
|
|
||||||
Copy to clipboard
|
|
||||||
</ClipboardButton>
|
|
||||||
{isPanelJSON && canEdit && (
|
{isPanelJSON && canEdit && (
|
||||||
<Button className={styles.toolbarItem} onClick={this.onApplyPanelModel}>
|
<Button className={styles.toolbarItem} onClick={this.onApplyPanelModel}>
|
||||||
Apply
|
Apply
|
||||||
@ -161,19 +135,24 @@ export class InspectJSONTab extends PureComponent<Props, State> {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
{isPanelJSON ? (
|
<AutoSizer disableWidth>
|
||||||
this.renderPanelJSON(styles)
|
{({ height }) => (
|
||||||
) : (
|
<CodeEditor
|
||||||
<div className={styles.viewer}>
|
width="100%"
|
||||||
<JSONFormatter json={this.getJSONObject(show)} />
|
height={height}
|
||||||
</div>
|
language="json"
|
||||||
)}
|
value={this.state.text}
|
||||||
|
readOnly={!isPanelJSON}
|
||||||
|
onBlur={this.onTextChanged}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</AutoSizer>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSaveModelJSON(panel: PanelModel): string {
|
function getPrettyJSON(obj: any): string {
|
||||||
return JSON.stringify(panel.getSaveModel(), null, 2);
|
return JSON.stringify(obj, null, 2);
|
||||||
}
|
}
|
||||||
|
1
public/test/mocks/style.ts
Normal file
1
public/test/mocks/style.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const style = 'style';
|
@ -1,5 +1,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
|
||||||
|
|
||||||
// https://github.com/visionmedia/debug/issues/701#issuecomment-505487361
|
// https://github.com/visionmedia/debug/issues/701#issuecomment-505487361
|
||||||
function shouldExclude(filename) {
|
function shouldExclude(filename) {
|
||||||
// There is external js code inside this which needs to be processed by babel.
|
// There is external js code inside this which needs to be processed by babel.
|
||||||
@ -15,6 +17,7 @@ function shouldExclude(filename) {
|
|||||||
'react-hook-form',
|
'react-hook-form',
|
||||||
'rc-trigger',
|
'rc-trigger',
|
||||||
'@iconscout/react-unicons',
|
'@iconscout/react-unicons',
|
||||||
|
'monaco-editor',
|
||||||
];
|
];
|
||||||
for (const package of packagesToProcessbyBabel) {
|
for (const package of packagesToProcessbyBabel) {
|
||||||
if (filename.indexOf(`node_modules/${package}`) > 0) {
|
if (filename.indexOf(`node_modules/${package}`) > 0) {
|
||||||
@ -58,6 +61,55 @@ module.exports = {
|
|||||||
node: {
|
node: {
|
||||||
fs: 'empty',
|
fs: 'empty',
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new MonacoWebpackPlugin({
|
||||||
|
// available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
|
||||||
|
filename: 'monaco-[name].worker.js',
|
||||||
|
languages: ['json', 'markdown', 'html', 'sql', 'mysql', 'pgsql'],
|
||||||
|
features: [
|
||||||
|
'!accessibilityHelp',
|
||||||
|
'bracketMatching',
|
||||||
|
'caretOperations',
|
||||||
|
'!clipboard',
|
||||||
|
'!codeAction',
|
||||||
|
'!codelens',
|
||||||
|
'!colorDetector',
|
||||||
|
'!comment',
|
||||||
|
'!contextmenu',
|
||||||
|
'!coreCommands',
|
||||||
|
'!cursorUndo',
|
||||||
|
'!dnd',
|
||||||
|
'!find',
|
||||||
|
'!folding',
|
||||||
|
'!fontZoom',
|
||||||
|
'!format',
|
||||||
|
'!gotoError',
|
||||||
|
'!gotoLine',
|
||||||
|
'!gotoSymbol',
|
||||||
|
'!hover',
|
||||||
|
'!iPadShowKeyboard',
|
||||||
|
'!inPlaceReplace',
|
||||||
|
'!inspectTokens',
|
||||||
|
'!linesOperations',
|
||||||
|
'!links',
|
||||||
|
'!multicursor',
|
||||||
|
'!parameterHints',
|
||||||
|
'!quickCommand',
|
||||||
|
'!quickOutline',
|
||||||
|
'!referenceSearch',
|
||||||
|
'!rename',
|
||||||
|
'!smartSelect',
|
||||||
|
'!snippets',
|
||||||
|
'!suggest',
|
||||||
|
'!toggleHighContrast',
|
||||||
|
'!toggleTabFocusMode',
|
||||||
|
'!transpose',
|
||||||
|
'!wordHighlighter',
|
||||||
|
'!wordOperations',
|
||||||
|
'!wordPartOperations',
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
/**
|
/**
|
||||||
@ -108,6 +160,11 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
// include: MONACO_DIR, // https://github.com/react-monaco-editor/react-monaco-editor
|
||||||
|
use: ['style-loader', 'css-loader'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/,
|
test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
|
34
yarn.lock
34
yarn.lock
@ -6456,6 +6456,14 @@
|
|||||||
"@types/prop-types" "*"
|
"@types/prop-types" "*"
|
||||||
csstype "^2.2.0"
|
csstype "^2.2.0"
|
||||||
|
|
||||||
|
"@types/react@^16.x":
|
||||||
|
version "16.9.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368"
|
||||||
|
integrity sha512-q0n0SsWcGc8nDqH2GJfWQWUOmZSJhXV64CjVN5SvcNti3TdEaA3AH0D8DwNmMdzjMAC/78tB8nAZIlV8yTz+zQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/prop-types" "*"
|
||||||
|
csstype "^2.2.0"
|
||||||
|
|
||||||
"@types/recompose@^0.30.7":
|
"@types/recompose@^0.30.7":
|
||||||
version "0.30.7"
|
version "0.30.7"
|
||||||
resolved "https://registry.yarnpkg.com/@types/recompose/-/recompose-0.30.7.tgz#0d47f3da3bdf889a4f36d4ca7531fac1eee1c6bd"
|
resolved "https://registry.yarnpkg.com/@types/recompose/-/recompose-0.30.7.tgz#0d47f3da3bdf889a4f36d4ca7531fac1eee1c6bd"
|
||||||
@ -10595,7 +10603,7 @@ cypress-file-upload@^4.0.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mime "^2.4.4"
|
mime "^2.4.4"
|
||||||
|
|
||||||
cypress@4.9.0:
|
cypress@^4.9.0:
|
||||||
version "4.9.0"
|
version "4.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.9.0.tgz#c188a3864ddf841c0fdc81a9e4eff5cf539cd1c1"
|
resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.9.0.tgz#c188a3864ddf841c0fdc81a9e4eff5cf539cd1c1"
|
||||||
integrity sha512-qGxT5E0j21FPryzhb0OBjCdhoR/n1jXtumpFFSBPYWsaZZhNaBvc3XlBUDEZKkkXPsqUFYiyhWdHN/zo0t5FcA==
|
integrity sha512-qGxT5E0j21FPryzhb0OBjCdhoR/n1jXtumpFFSBPYWsaZZhNaBvc3XlBUDEZKkkXPsqUFYiyhWdHN/zo0t5FcA==
|
||||||
@ -18292,10 +18300,17 @@ moment@2.26.0:
|
|||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
|
||||||
integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==
|
integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==
|
||||||
|
|
||||||
monaco-editor@0.15.6:
|
monaco-editor-webpack-plugin@1.9.0:
|
||||||
version "0.15.6"
|
version "1.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.15.6.tgz#d63b3b06f86f803464f003b252627c3eb4a09483"
|
resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.9.0.tgz#5b547281b9f404057dc5d8c5722390df9ac90be6"
|
||||||
integrity sha512-JoU9V9k6KqT9R9Tiw1RTU8ohZ+Xnf9DMg6Ktqqw5hILumwmq7xqa/KLXw513uTUsWbhtnHoSJYYR++u3pkyxJg==
|
integrity sha512-tOiiToc94E1sb50BgZ8q8WK/bxus77SRrwCqIpAB5er3cpX78SULbEBY4YPOB8kDolOzKRt30WIHG/D6gz69Ww==
|
||||||
|
dependencies:
|
||||||
|
loader-utils "^1.2.3"
|
||||||
|
|
||||||
|
monaco-editor@*, monaco-editor@0.20.0:
|
||||||
|
version "0.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
|
||||||
|
integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
|
||||||
|
|
||||||
moo@^0.4.3:
|
moo@^0.4.3:
|
||||||
version "0.4.3"
|
version "0.4.3"
|
||||||
@ -21914,6 +21929,15 @@ react-loadable@5.5.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.5.0"
|
prop-types "^15.5.0"
|
||||||
|
|
||||||
|
react-monaco-editor@0.36.0:
|
||||||
|
version "0.36.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.36.0.tgz#ac085c14f25fb072514c925596f6a06a711ee078"
|
||||||
|
integrity sha512-JVA5SZhOoYZ0DCdTwYgagtRb3jHo4KN7TVFiJauG+ZBAJWfDSTzavPIrwzWbgu8ahhDqDk4jUcYlOJL2BC/0UA==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "^16.x"
|
||||||
|
monaco-editor "*"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
|
||||||
react-popper-tooltip@^2.8.3:
|
react-popper-tooltip@^2.8.3:
|
||||||
version "2.9.1"
|
version "2.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.9.1.tgz#cc602c89a937aea378d9e2675b1ce62805beb4f6"
|
resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.9.1.tgz#cc602c89a937aea378d9e2675b1ce62805beb4f6"
|
||||||
|
Loading…
Reference in New Issue
Block a user