feeles-ide
Version:
The hackable and serializable IDE to make learning material
374 lines (310 loc) • 13.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf3 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _styles = require("@material-ui/core/styles");
var _propTypes = _interopRequireDefault(require("prop-types"));
var _typestyle = require("typestyle");
var _csx = require("csx");
var _jsBeautify = _interopRequireDefault(require("js-beautify"));
var _Button = _interopRequireDefault(require("@material-ui/core/Button"));
var _Typography = _interopRequireDefault(require("@material-ui/core/Typography"));
var _LinearProgress = _interopRequireDefault(require("@material-ui/core/LinearProgress"));
var _Stop = _interopRequireDefault(require("@material-ui/icons/Stop"));
var _red = _interopRequireDefault(require("@material-ui/core/colors/red"));
var _Reply = _interopRequireDefault(require("@material-ui/icons/Reply"));
var _CardFloatingBar = _interopRequireDefault(require("../CardFloatingBar"));
var _File = require("../../File/");
var _Editor = _interopRequireDefault(require("../EditorCard/Editor"));
var _excessiveCare = _interopRequireDefault(require("./excessiveCare"));
var _dec, _class, _class2, _temp;
var cn = {
root: (0, _typestyle.style)({
display: 'flex',
flexDirection: 'column'
}),
shoot: (0, _typestyle.style)({
marginRight: 9,
marginBottom: 4,
transform: (0, _csx.rotateY)((0, _csx.deg)(0))
}),
shooting: (0, _typestyle.style)({
transform: (0, _csx.rotateY)((0, _csx.deg)(180))
}),
label: (0, _typestyle.style)({
fontSize: '.8rem'
}),
error: (0, _typestyle.style)({
flex: '0 1 auto',
margin: 0,
padding: 8,
backgroundColor: _red.default['50'],
color: _red.default['500'],
fontFamily: 'Consolas, "Liberation Mono", Menlo, Courier, monospace',
overflow: 'scroll'
}),
restore: (0, _typestyle.style)({
margin: 4
}),
blank: (0, _typestyle.style)({
flex: 1
})
};
var getCn = function getCn(props, state) {
return {
editor: (0, _typestyle.style)({
position: 'relative',
boxSizing: 'border-box',
width: '100%',
height: state.height,
minHeight: 100,
transform: (0, _csx.translateX)(state.shooting ? -500 : 0),
opacity: state.shooting ? 0 : 1,
transition: props.theme.transitions.create()
})
};
};
var ShotPane = (_dec = (0, _styles.withTheme)(), _dec(_class = (_temp = _class2 =
/*#__PURE__*/
function (_PureComponent) {
(0, _inherits2.default)(ShotPane, _PureComponent);
function ShotPane() {
var _getPrototypeOf2;
var _this;
(0, _classCallCheck2.default)(this, ShotPane);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = (0, _possibleConstructorReturn2.default)(this, (_getPrototypeOf2 = (0, _getPrototypeOf3.default)(ShotPane)).call.apply(_getPrototypeOf2, [this].concat(args)));
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "state", {
shooting: false,
height: 0,
error: null,
loading: false,
canRestore: false,
file: _this.props.file || _File.SourceFile.shot(''),
cardAnchorEl: null
});
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleShot",
/*#__PURE__*/
(0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee() {
return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!_this.state.shooting) {
_context.next = 2;
break;
}
return _context.abrupt("return");
case 2:
_context.next = 4;
return _this.shotCode();
case 4:
_this.setState({
shooting: true
});
case 5:
case "end":
return _context.stop();
}
}
}, _callee, this);
})));
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleChange", function (cm) {
var canRestore = cm.getValue() !== _this.state.file.text;
_this.setState({
canRestore: canRestore
});
});
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleRestore", function () {
_this.codeMirror.setValue(_this.state.file.text);
});
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleViewportChange", function (cm) {
var lastLine = cm.lastLine() + 1;
var height = cm.heightAtLine(lastLine, 'local'); // もしエディタの描画領域が広過ぎて ShotCard が画面からはみ出すなら, height を更新しない
var cardAnchorEl = _this.state.cardAnchorEl;
if (cardAnchorEl) {
var offsetParent = cardAnchorEl.offsetParent,
offsetTop = cardAnchorEl.offsetTop;
var appendedHeight = height - _this.state.height;
var containerHeight = offsetParent.clientHeight - parseInt(offsetParent.style.paddingTop, 10) - parseInt(offsetParent.style.paddingBottom, 10);
if (offsetTop + appendedHeight >= containerHeight) {
return;
}
}
_this.setState({
height: height
});
});
return _this;
}
(0, _createClass2.default)(ShotPane, [{
key: "componentDidMount",
value: function componentDidMount() {
this.codeMirror.on('beforeChange', _excessiveCare.default);
this.codeMirror.on('change', this.handleChange);
this.codeMirror.on('swapDoc', this.handleChange);
this.codeMirror.on('viewportChange', this.handleViewportChange);
this.codeMirror.on('swapDoc', this.handleViewportChange);
this.handleViewportChange(this.codeMirror);
this.props.globalEvent.on('message.runCode', this.handleShot);
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps, prevState) {
var _this2 = this;
if (prevProps.file !== this.props.file) {
var file = this.props.file || _File.SourceFile.shot('');
this.setState({
file: file
});
}
if (!prevState.shooting && this.state.shooting) {
// shooting アニメーションをもとにもどす
setTimeout(function () {
_this2.setState({
shooting: false
});
}, 1000);
}
if (prevState.height !== this.state.height) {
setTimeout(function () {
// 表示可能領域が変わったので、トランジション後に再描画する
if (_this2.codeMirror) {
_this2.codeMirror.refresh();
}
}, 300);
} // ShotCard の中にある最も下の要素を取得する
var cardAnchorEl = document.querySelector('#ShotCard-BottomAnchor');
if (!prevState.cardAnchorEl && cardAnchorEl) {
this.setState({
cardAnchorEl: cardAnchorEl
});
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.props.globalEvent.off('message.runCode', this.handleShot);
}
}, {
key: "shotCode",
value: function () {
var _shotCode = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee2() {
var text, configs, formatted, name, file, request;
return _regenerator.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
text = this.codeMirror ? this.codeMirror.getValue('\n') : this.state.file.text; // コードのフォーマット
if (this.props.loadConfig('feelesrc').formatOnSendCode || false) {
// import .jsbeautifyrc
configs = this.props.loadConfig('jsbeautifyrc');
formatted = (0, _jsBeautify.default)(text, configs.js || {});
this.codeMirror.setValue(formatted);
} // コードをファイルにする
name = this.state.file.name;
file = _File.SourceFile.shot(text, name); // frame に shot をおくる
request = {
query: 'shot',
value: file.serialize()
};
this.props.globalEvent.emit('postMessage', request);
case 6:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
function shotCode() {
return _shotCode.apply(this, arguments);
}
return shotCode;
}()
}, {
key: "render",
value: function render() {
var _this3 = this;
var dcn = getCn(this.props, this.state);
var _this$props = this.props,
localization = _this$props.localization,
getConfig = _this$props.getConfig,
loadConfig = _this$props.loadConfig;
var shooting = this.state.shooting; // TODO: Enter で実行か Shift-Enter で実行か
var _loadConfig = loadConfig('feelesrc'),
sendCodeOnEnter = _loadConfig.sendCodeOnEnter;
var shootKey = sendCodeOnEnter ? 'Enter' : 'Ctrl-Enter';
var extraKeys = (0, _defineProperty2.default)({}, shootKey, this.handleShot);
return _react.default.createElement(_react.default.Fragment, null, this.state.error ? _react.default.createElement("pre", {
className: cn.error
}, this.state.error.message) : null, this.state.loading ? _react.default.createElement(_LinearProgress.default, null) : null, _react.default.createElement(_CardFloatingBar.default, null, _react.default.createElement("span", null, localization.shotCard.title), _react.default.createElement(_Button.default, {
variant: "contained",
color: "secondary",
onClick: this.handleRestore,
className: cn.restore,
disabled: !this.state.canRestore
}, localization.shotCard.restore), _react.default.createElement("div", {
className: cn.blank
}), _react.default.createElement(_Typography.default, {
className: cn.label,
color: "textSecondary"
}, localization.shotCard.shoot), _react.default.createElement(_Button.default, {
variant: "contained",
color: "primary",
disabled: this.state.shooting,
onClick: this.handleShot,
className: (0, _typestyle.classes)(cn.shoot, shooting && cn.shooting)
}, localization.shotCard.button, this.state.shooting ? _react.default.createElement(_Stop.default, null) : _react.default.createElement(_Reply.default, null))), _react.default.createElement("div", {
className: dcn.editor
}, _react.default.createElement(_Editor.default, {
isSelected: true,
isCared: true,
file: this.state.file,
getConfig: getConfig,
codemirrorRef: function codemirrorRef(ref) {
return _this3.codeMirror = ref;
},
snippets: this.props.completes,
extraKeys: extraKeys,
lineNumbers: false,
findFile: this.props.findFile,
loadConfig: this.props.loadConfig,
fileView: this.props.fileView,
handleSetLinkObjects: this.props.handleSetLinkObjects
})));
}
}]);
return ShotPane;
}(_react.PureComponent), (0, _defineProperty2.default)(_class2, "propTypes", {
theme: _propTypes.default.object.isRequired,
fileView: _propTypes.default.object.isRequired,
files: _propTypes.default.array.isRequired,
findFile: _propTypes.default.func.isRequired,
localization: _propTypes.default.object.isRequired,
getConfig: _propTypes.default.func.isRequired,
loadConfig: _propTypes.default.func.isRequired,
file: _propTypes.default.object,
completes: _propTypes.default.array,
globalEvent: _propTypes.default.object.isRequired,
handleSetLinkObjects: _propTypes.default.func.isRequired
}), _temp)) || _class);
exports.default = ShotPane;