UNPKG

feeles-ide

Version:

The hackable and serializable IDE to make learning material

374 lines (310 loc) 13.4 kB
"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;