Merge pull request #1 from Bouncey/feat/monacoEditor
Feat/monaco editor
This commit is contained in:
committed by
Mrugesh Mohapatra
parent
939028df20
commit
1f5abb3dde
@ -1,4 +1,6 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
|
|
||||||
const { dasherize } = require('./utils');
|
const { dasherize } = require('./utils');
|
||||||
const { viewTypes } = require('./utils/challengeTypes');
|
const { viewTypes } = require('./utils/challengeTypes');
|
||||||
const { blockNameify } = require('./utils/blockNameify');
|
const { blockNameify } = require('./utils/blockNameify');
|
||||||
@ -84,3 +86,27 @@ exports.createPages = ({ graphql, boundActionCreators }) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.modifyWebpackConfig = ({ config, stage, babelConfig }) => {
|
||||||
|
if (stage === 'build-javascript' || stage === 'develop') {
|
||||||
|
config.plugin('CopyWebpackPlugin', CopyWebpackPlugin, [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
from: path.resolve(__dirname, './node_modules/monaco-editor/min/vs'),
|
||||||
|
to: 'vs'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
// remove the default 'js' loader so we can create our own
|
||||||
|
config.removeLoader('js');
|
||||||
|
// these modules are shipped with es6 code, we need to transform them due
|
||||||
|
// to the version of the uglifyjs plugin gatsby is using
|
||||||
|
config.loader('js', {
|
||||||
|
test: /\.jsx?$/,
|
||||||
|
exclude: /(node_modules|bower_components)\/(?!ansi-styles|chalk)/,
|
||||||
|
loader: 'babel',
|
||||||
|
query: babelConfig
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
"\\.(jpg|jpeg|png|svg|woff|woff2)$": "<rootDir>/src/__mocks__/fileMock.js",
|
'\\.(jpg|jpeg|png|svg|woff|woff2)$': '<rootDir>/src/__mocks__/fileMock.js',
|
||||||
// Plain CSS - match css files that don't end with '.module.css' https://regex101.com/r/VzwrKH/4
|
// Plain CSS - match css files that don't end with
|
||||||
"^(?!.*\\.module\\.css$).*\\.css$": "<rootDir>/src/__mocks__/styleMock.js",
|
// '.module.css' https://regex101.com/r/VzwrKH/4
|
||||||
|
'^(?!.*\\.module\\.css$).*\\.css$': '<rootDir>/src/__mocks__/styleMock.js',
|
||||||
// CSS Modules - match files that end with 'module.css'
|
// CSS Modules - match files that end with 'module.css'
|
||||||
"\\.module\\.css$": "identity-obj-proxy" // CSS modules
|
'\\.module\\.css$': 'identity-obj-proxy'
|
||||||
},
|
},
|
||||||
testPathIgnorePatterns: ["/node_modules/", "<rootDir>/.cache/"],
|
testPathIgnorePatterns: ['/node_modules/', '<rootDir>/.cache/'],
|
||||||
globals: {
|
globals: {
|
||||||
__PATH_PREFIX__: ""
|
__PATH_PREFIX__: ''
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"babel-standalone": "^6.26.0",
|
"babel-standalone": "^6.26.0",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"codemirror": "^5.36.0",
|
"copy-webpack-plugin": "^4.5.1",
|
||||||
"debug": "^3.1.0",
|
"debug": "^3.1.0",
|
||||||
"dotenv": "^5.0.1",
|
"dotenv": "^5.0.1",
|
||||||
"enzyme": "^3.3.0",
|
"enzyme": "^3.3.0",
|
||||||
@ -29,9 +29,9 @@
|
|||||||
"mongodb": "^3.0.5",
|
"mongodb": "^3.0.5",
|
||||||
"react": "16",
|
"react": "16",
|
||||||
"react-bootstrap": "^0.32.1",
|
"react-bootstrap": "^0.32.1",
|
||||||
"react-codemirror2": "^4.2.1",
|
|
||||||
"react-dom": "16",
|
"react-dom": "16",
|
||||||
"react-helmet": "^5.2.0",
|
"react-helmet": "^5.2.0",
|
||||||
|
"react-monaco-editor": "^0.14.1",
|
||||||
"react-redux": "^5.0.7",
|
"react-redux": "^5.0.7",
|
||||||
"react-reflex": "^2.2.1",
|
"react-reflex": "^2.2.1",
|
||||||
"react-router-redux": "^5.0.0-alpha.9",
|
"react-router-redux": "^5.0.0-alpha.9",
|
||||||
@ -52,14 +52,14 @@
|
|||||||
"build:frame-runner": "webpack --config ./webpack-frame-runner.js",
|
"build:frame-runner": "webpack --config ./webpack-frame-runner.js",
|
||||||
"build:loop-protect": "webpack --config ./webpack-loop-protect.js",
|
"build:loop-protect": "webpack --config ./webpack-loop-protect.js",
|
||||||
"develop": "yarn build:frame-runner && gatsby develop",
|
"develop": "yarn build:frame-runner && gatsby develop",
|
||||||
"format": "yarn format:gatsby && yarn format:src",
|
"format": "yarn format:gatsby && yarn format:src && yarn lint",
|
||||||
"format:gatsby": "prettier --write './gatsby*.js'",
|
"format:gatsby": "prettier --write './gatsby*.js'",
|
||||||
"format:src": "prettier --write './src/**/*.js'",
|
"format:src": "prettier --write './src/**/*.js'",
|
||||||
"lint": "yarn lint:gatsby && yarn lint:src",
|
"lint": "yarn lint:gatsby && yarn lint:src",
|
||||||
"lint:gatsby": "eslint ./gatsby*.js --fix",
|
"lint:gatsby": "eslint ./gatsby*.js --fix",
|
||||||
"lint:src": "eslint ./src . --fix",
|
"lint:src": "eslint ./src . --fix",
|
||||||
"pretty": "yarn format && yarn lint",
|
"pretty": "yarn format && yarn lint",
|
||||||
"test": "jest src",
|
"test": "yarn format && jest src",
|
||||||
"test:watch": "jest --watch src"
|
"test:watch": "jest --watch src"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
/* eslint-disable */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const mockComponent = name => props =>
|
const mockComponent = name => props =>
|
||||||
React.createElement(name, props, props.children);
|
React.createElement(name, props, props.children);
|
||||||
|
|
||||||
export default mockComponent('MockedLink');
|
export default mockComponent('MockedLink');
|
||||||
|
@ -13,7 +13,6 @@ const propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class ShowMap extends PureComponent {
|
class ShowMap extends PureComponent {
|
||||||
|
|
||||||
renderSuperBlocks(superBlocks) {
|
renderSuperBlocks(superBlocks) {
|
||||||
const { nodes } = this.props;
|
const { nodes } = this.props;
|
||||||
return superBlocks.map(superBlock => (
|
return superBlocks.map(superBlock => (
|
||||||
|
@ -12,8 +12,6 @@ Enzyme.configure({ adapter: new Adapter() });
|
|||||||
const renderer = new ShallowRenderer();
|
const renderer = new ShallowRenderer();
|
||||||
|
|
||||||
test('<Map /> snapshot', () => {
|
test('<Map /> snapshot', () => {
|
||||||
const component = renderer.render(
|
const component = renderer.render(<Map nodes={mockNodes} />);
|
||||||
<Map nodes={mockNodes} />,
|
|
||||||
);
|
|
||||||
expect(component).toMatchSnapshot('Map');
|
expect(component).toMatchSnapshot('Map');
|
||||||
});
|
});
|
||||||
|
@ -15,65 +15,53 @@ const renderer = new ShallowRenderer();
|
|||||||
test('<Block /> not expanded snapshot', () => {
|
test('<Block /> not expanded snapshot', () => {
|
||||||
const toggleSpy = sinon.spy();
|
const toggleSpy = sinon.spy();
|
||||||
const componentToRender = (
|
const componentToRender = (
|
||||||
<Block
|
<Block
|
||||||
blockDashedName='block-a'
|
blockDashedName='block-a'
|
||||||
challenges={
|
challenges={mockNodes.filter(node => node.block === 'block-a')}
|
||||||
mockNodes.filter(
|
isExpanded={false}
|
||||||
node => node.block === 'block-a'
|
toggleBlock={toggleSpy}
|
||||||
)
|
/>
|
||||||
}
|
);
|
||||||
isExpanded={false}
|
|
||||||
toggleBlock={toggleSpy}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
const component = renderer.render(componentToRender);
|
const component = renderer.render(componentToRender);
|
||||||
|
|
||||||
expect(component).toMatchSnapshot('block-not-expanded');
|
expect(component).toMatchSnapshot('block-not-expanded');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
test('<Block expanded snapshot', () => {
|
test('<Block expanded snapshot', () => {
|
||||||
const toggleSpy = sinon.spy();
|
const toggleSpy = sinon.spy();
|
||||||
const componentToRender = (
|
const componentToRender = (
|
||||||
<Block
|
<Block
|
||||||
blockDashedName='block-a'
|
blockDashedName='block-a'
|
||||||
challenges={
|
challenges={mockNodes.filter(node => node.block === 'block-a')}
|
||||||
mockNodes.filter(
|
isExpanded={true}
|
||||||
node => node.block === 'block-a'
|
toggleBlock={toggleSpy}
|
||||||
)
|
/>
|
||||||
}
|
);
|
||||||
isExpanded={true}
|
|
||||||
toggleBlock={toggleSpy}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const component = renderer.render(componentToRender);
|
const component = renderer.render(componentToRender);
|
||||||
|
|
||||||
expect(component).toMatchSnapshot('block-expanded');
|
expect(component).toMatchSnapshot('block-expanded');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
test('<Block /> should handle toggle clicks correctly', () => {
|
test('<Block /> should handle toggle clicks correctly', () => {
|
||||||
const toggleSpy = sinon.spy();
|
const toggleSpy = sinon.spy();
|
||||||
const props = {
|
const props = {
|
||||||
blockDashedName: 'block-a',
|
blockDashedName: 'block-a',
|
||||||
challenges: mockNodes.filter(
|
challenges: mockNodes.filter(node => node.block === 'block-a'),
|
||||||
node => node.block === 'block-a'
|
|
||||||
),
|
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
toggleBlock: toggleSpy
|
toggleBlock: toggleSpy
|
||||||
};
|
};
|
||||||
|
|
||||||
const componentToRender = (
|
const componentToRender = <Block {...props} />;
|
||||||
<Block { ...props } />
|
|
||||||
);
|
|
||||||
|
|
||||||
const enzymeWrapper = Enzyme.shallow(componentToRender);
|
const enzymeWrapper = Enzyme.shallow(componentToRender);
|
||||||
|
|
||||||
expect(toggleSpy.called).toBe(false);
|
expect(toggleSpy.called).toBe(false);
|
||||||
expect(
|
expect(
|
||||||
enzymeWrapper.find('.map-title').find('h5').text()
|
enzymeWrapper
|
||||||
|
.find('.map-title')
|
||||||
|
.find('h5')
|
||||||
|
.text()
|
||||||
).toBe('Block A');
|
).toBe('Block A');
|
||||||
|
|
||||||
enzymeWrapper.find('.map-title').simulate('click');
|
enzymeWrapper.find('.map-title').simulate('click');
|
||||||
@ -84,9 +72,10 @@ test('<Block /> should handle toggle clicks correctly', () => {
|
|||||||
enzymeWrapper.setProps({ ...props, isExpanded: true });
|
enzymeWrapper.setProps({ ...props, isExpanded: true });
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
enzymeWrapper.find('.map-title').find('h5').text()
|
enzymeWrapper
|
||||||
|
.find('.map-title')
|
||||||
|
.find('h5')
|
||||||
|
.text()
|
||||||
).toBe('Block A');
|
).toBe('Block A');
|
||||||
expect(
|
expect(enzymeWrapper.find('ul').length).toBe(1);
|
||||||
enzymeWrapper.find('ul').length
|
|
||||||
).toBe(1);
|
|
||||||
});
|
});
|
||||||
|
@ -20,13 +20,10 @@ test('<SuperBlock /> not expanded snapshot', () => {
|
|||||||
superBlock: 'Super Block One',
|
superBlock: 'Super Block One',
|
||||||
toggleSuperBlock: toggleSpy
|
toggleSuperBlock: toggleSpy
|
||||||
};
|
};
|
||||||
const componentToRender = (
|
const componentToRender = <SuperBlock {...props} />;
|
||||||
<SuperBlock { ...props } />
|
|
||||||
);
|
|
||||||
const component = renderer.render(componentToRender);
|
const component = renderer.render(componentToRender);
|
||||||
|
|
||||||
expect(component).toMatchSnapshot('superBlock-not-expanded');
|
expect(component).toMatchSnapshot('superBlock-not-expanded');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('<SuperBlock /> expanded snapshot', () => {
|
test('<SuperBlock /> expanded snapshot', () => {
|
||||||
@ -37,9 +34,7 @@ test('<SuperBlock /> expanded snapshot', () => {
|
|||||||
superBlock: 'Super Block One',
|
superBlock: 'Super Block One',
|
||||||
toggleSuperBlock: toggleSpy
|
toggleSuperBlock: toggleSpy
|
||||||
};
|
};
|
||||||
const componentToRender = (
|
const componentToRender = <SuperBlock {...props} />;
|
||||||
<SuperBlock { ...props } />
|
|
||||||
);
|
|
||||||
const component = renderer.render(componentToRender);
|
const component = renderer.render(componentToRender);
|
||||||
|
|
||||||
expect(component).toMatchSnapshot('superBlock-expanded');
|
expect(component).toMatchSnapshot('superBlock-expanded');
|
||||||
@ -53,18 +48,17 @@ test('<SuperBlock should handle toggle clicks correctly', () => {
|
|||||||
superBlock: 'Super Block One',
|
superBlock: 'Super Block One',
|
||||||
toggleSuperBlock: toggleSpy
|
toggleSuperBlock: toggleSpy
|
||||||
};
|
};
|
||||||
const componentToRender = (
|
const componentToRender = <SuperBlock {...props} />;
|
||||||
<SuperBlock { ...props } />
|
|
||||||
);
|
|
||||||
const enzymeWrapper = Enzyme.shallow(componentToRender);
|
const enzymeWrapper = Enzyme.shallow(componentToRender);
|
||||||
|
|
||||||
expect(toggleSpy.called).toBe(false);
|
expect(toggleSpy.called).toBe(false);
|
||||||
expect(
|
expect(
|
||||||
enzymeWrapper.find('.map-title').find('h4').text()
|
enzymeWrapper
|
||||||
|
.find('.map-title')
|
||||||
|
.find('h4')
|
||||||
|
.text()
|
||||||
).toBe('Super Block One');
|
).toBe('Super Block One');
|
||||||
expect(
|
expect(enzymeWrapper.find('ul').length).toBe(0);
|
||||||
enzymeWrapper.find('ul').length
|
|
||||||
).toBe(0);
|
|
||||||
|
|
||||||
enzymeWrapper.find('.map-title').simulate('click');
|
enzymeWrapper.find('.map-title').simulate('click');
|
||||||
|
|
||||||
@ -74,9 +68,10 @@ test('<SuperBlock should handle toggle clicks correctly', () => {
|
|||||||
enzymeWrapper.setProps({ ...props, isExpanded: true });
|
enzymeWrapper.setProps({ ...props, isExpanded: true });
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
enzymeWrapper.find('.map-title').find('h4').text()
|
enzymeWrapper
|
||||||
|
.find('.map-title')
|
||||||
|
.find('h4')
|
||||||
|
.text()
|
||||||
).toBe('Super Block One');
|
).toBe('Super Block One');
|
||||||
expect(
|
expect(enzymeWrapper.find('ul').length).toBe(1);
|
||||||
enzymeWrapper.find('ul').length
|
|
||||||
).toBe(1);
|
|
||||||
});
|
});
|
||||||
|
@ -10,10 +10,7 @@ import Spacer from './Spacer';
|
|||||||
Enzyme.configure({ adapter: new Adapter() });
|
Enzyme.configure({ adapter: new Adapter() });
|
||||||
|
|
||||||
test('<Spacer /> snapshot', () => {
|
test('<Spacer /> snapshot', () => {
|
||||||
const component = renderer.create(
|
const component = renderer.create(<Spacer />);
|
||||||
<Spacer />,
|
|
||||||
);
|
|
||||||
let tree = component.toJSON();
|
let tree = component.toJSON();
|
||||||
expect(tree).toMatchSnapshot();
|
expect(tree).toMatchSnapshot();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -2,18 +2,10 @@ import React, { PureComponent } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
import MonacoEditor from 'react-monaco-editor';
|
||||||
|
|
||||||
import { executeChallenge, updateFile } from '../../redux';
|
import { executeChallenge, updateFile } from '../../redux';
|
||||||
|
|
||||||
import 'codemirror/lib/codemirror.css';
|
|
||||||
import 'codemirror/theme/material.css';
|
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
require('codemirror/mode/htmlmixed/htmlmixed');
|
|
||||||
require('codemirror/mode/javascript/javascript');
|
|
||||||
}
|
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
contents: PropTypes.string,
|
contents: PropTypes.string,
|
||||||
executeChallenge: PropTypes.func.isRequired,
|
executeChallenge: PropTypes.func.isRequired,
|
||||||
@ -34,7 +26,8 @@ const mapDispatchToProps = dispatch =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const modeMap = {
|
const modeMap = {
|
||||||
html: 'htmlmixed',
|
css: 'css',
|
||||||
|
html: 'html',
|
||||||
js: 'javascript',
|
js: 'javascript',
|
||||||
jsx: 'javascript'
|
jsx: 'javascript'
|
||||||
};
|
};
|
||||||
@ -42,60 +35,57 @@ const modeMap = {
|
|||||||
class Editor extends PureComponent {
|
class Editor extends PureComponent {
|
||||||
constructor(...props) {
|
constructor(...props) {
|
||||||
super(...props);
|
super(...props);
|
||||||
|
this.options = {
|
||||||
|
selectOnLineNumbers: true
|
||||||
|
};
|
||||||
this._editor = null;
|
this._editor = null;
|
||||||
|
|
||||||
|
this.focusEditor = this.focusEditor.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange = editorValue => {
|
componentWillUnmount() {
|
||||||
|
document.removeEventListener('keyup', this.focusEditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
editorDidMount(editor, monaco) {
|
||||||
|
this._editor = editor;
|
||||||
|
document.addEventListener('keyup', this.focusEditor);
|
||||||
|
this._editor.addAction({
|
||||||
|
id: 'execute-challenge',
|
||||||
|
label: 'Run tests',
|
||||||
|
keybindings: [
|
||||||
|
/* eslint-disable no-bitwise */
|
||||||
|
monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter)
|
||||||
|
],
|
||||||
|
run: this.props.executeChallenge
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
focusEditor(e) {
|
||||||
|
// e key to focus editor
|
||||||
|
if (e.keyCode === 69) {
|
||||||
|
console.log('focusing');
|
||||||
|
this._editor.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(editorValue) {
|
||||||
const { updateFile, fileKey } = this.props;
|
const { updateFile, fileKey } = this.props;
|
||||||
updateFile({ key: fileKey, editorValue });
|
updateFile({ key: fileKey, editorValue });
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { contents, executeChallenge, ext } = this.props;
|
const { contents, ext } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='classic-editor editor'>
|
<div className='classic-editor editor'>
|
||||||
<CodeMirror
|
<base href='/' />
|
||||||
onBeforeChange={(editor, something, newValue) =>
|
<MonacoEditor
|
||||||
this.handleChange(newValue)
|
editorDidMount={::this.editorDidMount}
|
||||||
}
|
language={modeMap[ext]}
|
||||||
options={{
|
onChange={::this.onChange}
|
||||||
mode: modeMap[ext],
|
options={this.options}
|
||||||
theme: 'material',
|
theme='vs-dark'
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true,
|
|
||||||
extraKeys: {
|
|
||||||
Esc() {
|
|
||||||
document.activeElement.blur();
|
|
||||||
},
|
|
||||||
Tab(cm) {
|
|
||||||
if (cm.somethingSelected()) {
|
|
||||||
return cm.indentSelection('add');
|
|
||||||
}
|
|
||||||
const spaces = Array(cm.getOption('indentUnit') + 1).join(' ');
|
|
||||||
return cm.replaceSelection(spaces);
|
|
||||||
},
|
|
||||||
'Shift-Tab': function(cm) {
|
|
||||||
return cm.indentSelection('subtract');
|
|
||||||
},
|
|
||||||
'Ctrl-Enter': function() {
|
|
||||||
executeChallenge();
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
'Cmd-Enter': function() {
|
|
||||||
executeChallenge();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// TODO: Not working in cm2
|
|
||||||
// 'Ctrl-/': function(cm) {
|
|
||||||
// cm.toggleComment();
|
|
||||||
// },
|
|
||||||
// 'Cmd-/': function(cm) {
|
|
||||||
// cm.toggleComment();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
value={contents}
|
value={contents}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,28 +1,35 @@
|
|||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
import MonacoEditor from 'react-monaco-editor';
|
||||||
|
|
||||||
import './output.css';
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
lineNumbers: false,
|
|
||||||
lineWrapping: true,
|
|
||||||
mode: 'javascript',
|
|
||||||
readOnly: 'nocursor'
|
|
||||||
};
|
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
defaultOutput: PropTypes.string,
|
defaultOutput: PropTypes.string,
|
||||||
output: PropTypes.string
|
output: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
lineNumbers: false,
|
||||||
|
minimap: {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
scrollbar: {
|
||||||
|
vertical: 'hidden',
|
||||||
|
horizontal: 'hidden'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function Output({ output, defaultOutput }) {
|
function Output({ output, defaultOutput }) {
|
||||||
return (
|
return (
|
||||||
<CodeMirror
|
<Fragment>
|
||||||
className='challenge-log'
|
<base href='/' />
|
||||||
options={{ ...defaultOptions, theme: 'material' }}
|
<MonacoEditor
|
||||||
value={output || defaultOutput}
|
className='challenge-output'
|
||||||
/>
|
height={150}
|
||||||
|
options={options}
|
||||||
|
value={output ? output : defaultOutput}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
.react-codemirror2.challenge-log > .CodeMirror {
|
|
||||||
height: 150px;
|
|
||||||
}
|
|
@ -2101,10 +2101,6 @@ code-point-at@^1.0.0:
|
|||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||||
|
|
||||||
codemirror@^5.36.0:
|
|
||||||
version "5.36.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.36.0.tgz#1172ad9dc298056c06e0b34e5ccd23825ca15b40"
|
|
||||||
|
|
||||||
collection-visit@^1.0.0:
|
collection-visit@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
|
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
|
||||||
@ -2326,6 +2322,19 @@ copy-descriptor@^0.1.0:
|
|||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
||||||
|
|
||||||
|
copy-webpack-plugin@^4.5.1:
|
||||||
|
version "4.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.5.1.tgz#fc4f68f4add837cc5e13d111b20715793225d29c"
|
||||||
|
dependencies:
|
||||||
|
cacache "^10.0.4"
|
||||||
|
find-cache-dir "^1.0.0"
|
||||||
|
globby "^7.1.1"
|
||||||
|
is-glob "^4.0.0"
|
||||||
|
loader-utils "^1.1.0"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
p-limit "^1.0.0"
|
||||||
|
serialize-javascript "^1.4.0"
|
||||||
|
|
||||||
copyfiles@^1.2.0:
|
copyfiles@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-1.2.0.tgz#a8da3ac41aa2220ae29bd3c58b6984294f2c593c"
|
resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-1.2.0.tgz#a8da3ac41aa2220ae29bd3c58b6984294f2c593c"
|
||||||
@ -2814,6 +2823,13 @@ diffie-hellman@^5.0.0:
|
|||||||
miller-rabin "^4.0.0"
|
miller-rabin "^4.0.0"
|
||||||
randombytes "^2.0.0"
|
randombytes "^2.0.0"
|
||||||
|
|
||||||
|
dir-glob@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034"
|
||||||
|
dependencies:
|
||||||
|
arrify "^1.0.1"
|
||||||
|
path-type "^3.0.0"
|
||||||
|
|
||||||
discontinuous-range@1.0.0:
|
discontinuous-range@1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
|
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
|
||||||
@ -4360,6 +4376,17 @@ globby@^6.1.0:
|
|||||||
pify "^2.0.0"
|
pify "^2.0.0"
|
||||||
pinkie-promise "^2.0.0"
|
pinkie-promise "^2.0.0"
|
||||||
|
|
||||||
|
globby@^7.1.1:
|
||||||
|
version "7.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680"
|
||||||
|
dependencies:
|
||||||
|
array-union "^1.0.1"
|
||||||
|
dir-glob "^2.0.0"
|
||||||
|
glob "^7.1.2"
|
||||||
|
ignore "^3.3.5"
|
||||||
|
pify "^3.0.0"
|
||||||
|
slash "^1.0.0"
|
||||||
|
|
||||||
got@^6.7.1:
|
got@^6.7.1:
|
||||||
version "6.7.1"
|
version "6.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
|
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
|
||||||
@ -4729,7 +4756,7 @@ iferr@^0.1.5:
|
|||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
|
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
|
||||||
|
|
||||||
ignore@^3.3.3:
|
ignore@^3.3.3, ignore@^3.3.5:
|
||||||
version "3.3.7"
|
version "3.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
|
||||||
|
|
||||||
@ -5874,7 +5901,7 @@ loader-utils@^0.2.11, loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^
|
|||||||
json5 "^0.5.0"
|
json5 "^0.5.0"
|
||||||
object-assign "^4.0.1"
|
object-assign "^4.0.1"
|
||||||
|
|
||||||
loader-utils@^1.0.2:
|
loader-utils@^1.0.2, loader-utils@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
|
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6342,6 +6369,10 @@ moment@2.x.x, moment@^2.16.0:
|
|||||||
version "2.21.0"
|
version "2.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a"
|
||||||
|
|
||||||
|
monaco-editor@^0.10.0:
|
||||||
|
version "0.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.10.1.tgz#8c96c4f15b6b5258bf92cbde93cad8a7e3007e14"
|
||||||
|
|
||||||
mongodb-core@2.1.19:
|
mongodb-core@2.1.19:
|
||||||
version "2.1.19"
|
version "2.1.19"
|
||||||
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.19.tgz#00fbd5e5a3573763b9171cfd844e60a8f2a3a18b"
|
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.19.tgz#00fbd5e5a3573763b9171cfd844e60a8f2a3a18b"
|
||||||
@ -6891,7 +6922,7 @@ p-finally@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
||||||
|
|
||||||
p-limit@^1.1.0:
|
p-limit@^1.0.0, p-limit@^1.1.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
|
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7063,7 +7094,7 @@ path-to-regexp@^1.7.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isarray "0.0.1"
|
isarray "0.0.1"
|
||||||
|
|
||||||
path-type@3.0.0:
|
path-type@3.0.0, path-type@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7959,10 +7990,6 @@ react-bootstrap@^0.32.1:
|
|||||||
uncontrollable "^4.1.0"
|
uncontrollable "^4.1.0"
|
||||||
warning "^3.0.0"
|
warning "^3.0.0"
|
||||||
|
|
||||||
react-codemirror2@^4.2.1:
|
|
||||||
version "4.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-4.2.1.tgz#4ad3c5c60ebbcb34880f961721b51527324ec021"
|
|
||||||
|
|
||||||
react-deep-force-update@^2.1.1:
|
react-deep-force-update@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909"
|
resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909"
|
||||||
@ -8052,6 +8079,13 @@ react-measure@^2.0.2:
|
|||||||
prop-types "^15.5.10"
|
prop-types "^15.5.10"
|
||||||
resize-observer-polyfill "^1.4.2"
|
resize-observer-polyfill "^1.4.2"
|
||||||
|
|
||||||
|
react-monaco-editor@^0.14.1:
|
||||||
|
version "0.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.14.1.tgz#f5163e119e8a7dc79b992cb3fd7af887547d7efd"
|
||||||
|
dependencies:
|
||||||
|
monaco-editor "^0.10.0"
|
||||||
|
prop-types "^15.5.10"
|
||||||
|
|
||||||
react-overlays@^0.8.0:
|
react-overlays@^0.8.0:
|
||||||
version "0.8.3"
|
version "0.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.8.3.tgz#fad65eea5b24301cca192a169f5dddb0b20d3ac5"
|
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.8.3.tgz#fad65eea5b24301cca192a169f5dddb0b20d3ac5"
|
||||||
|
Reference in New Issue
Block a user