feeles-ide
Version:
The hackable and serializable IDE to make learning material
209 lines (167 loc) • 6.86 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
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 _propTypes = _interopRequireDefault(require("prop-types"));
var _codemirror = _interopRequireDefault(require("codemirror"));
var _deepEqual = _interopRequireDefault(require("deep-equal"));
var _includes = _interopRequireDefault(require("lodash/includes"));
var CodeMirrorComponent =
/*#__PURE__*/
function (_PureComponent) {
(0, _inherits2.default)(CodeMirrorComponent, _PureComponent);
function CodeMirrorComponent() {
var _getPrototypeOf2;
var _this;
(0, _classCallCheck2.default)(this, CodeMirrorComponent);
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)(CodeMirrorComponent)).call.apply(_getPrototypeOf2, [this].concat(args)));
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "state", {
// File ごとに存在する CodeMirror.Doc インスタンスのキャッシュ
docs: new Map()
});
return _this;
}
(0, _createClass2.default)(CodeMirrorComponent, [{
key: "componentDidMount",
value: function componentDidMount() {
// initialize CodeMirror
this.codeMirror = _codemirror.default.fromTextArea(this.ref, this.options);
var id = this.props.id;
var doc = this.codeMirror.getDoc();
doc.setValue(this.props.value); // set default value
doc.clearHistory();
this.state.docs.set(id, doc);
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.state.docs.clear();
this.codeMirror.toTextArea();
this.codeMirror = null; // GC??
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
// タブ, value の更新
if (prevProps.id !== this.props.id) {
// 次のタブ (or undefined)
var doc = this.state.docs.get(this.props.id);
if (!doc) {
// 新しく開かれたタブ(キャッシュに存在しない)
// copy をもとに新しい Doc を作り、 value を更新
doc = this.codeMirror.getDoc().copy(false);
doc.setValue(this.props.value); // value の更新
doc.clearHistory();
this.state.docs.set(this.props.id, doc);
} // 現在のタブと入れ替え
this.codeMirror.swapDoc(doc);
} else {
// 同じタブ(ファイル)
this.setValueIfDifferent(this.props.value); // value の更新
} // options の更新
var ignoreKeys = ['id', 'value'];
var _arr = Object.entries(this.props);
for (var _i = 0; _i < _arr.length; _i++) {
var _arr$_i = (0, _slicedToArray2.default)(_arr[_i], 2),
key = _arr$_i[0],
nextValue = _arr$_i[1];
if ((0, _includes.default)(ignoreKeys, key)) continue;
if (!(0, _deepEqual.default)(prevProps[key], this.props[key])) {
// options の変更を CodeMirror に伝える
this.codeMirror.setOption(key, nextValue);
}
}
}
}, {
key: "getCodeMirror",
value: function getCodeMirror() {
return this.codeMirror;
}
}, {
key: "setValueIfDifferent",
value: function setValueIfDifferent(nextValue) {
// 現在エディタに表示されている文章と比較し、違ったら setValue する
var value = this.codeMirror.getValue();
if (value !== nextValue) {
// スクロール位置を保持する
var _this$codeMirror$getS = this.codeMirror.getScrollInfo(),
left = _this$codeMirror$getS.left,
top = _this$codeMirror$getS.top;
this.codeMirror.setValue(value);
this.codeMirror.scrollTo(left, top);
}
}
}, {
key: "render",
value: function render() {
var _this2 = this;
return _react.default.createElement("textarea", {
ref: function ref(_ref) {
return _this2.ref = _ref;
}
});
}
}, {
key: "options",
get: function get() {
var gutters = [];
if (this.props.lineNumbers) {
gutters.push('CodeMirror-linenumbers');
}
if (this.props.foldGutter) {
gutters.push('CodeMirror-foldgutter');
}
return (0, _objectSpread2.default)({}, this.props, {
gutters: gutters
});
}
}]);
return CodeMirrorComponent;
}(_react.PureComponent);
exports.default = CodeMirrorComponent;
(0, _defineProperty2.default)(CodeMirrorComponent, "propTypes", {
id: _propTypes.default.string.isRequired,
// CodeMirror options
value: _propTypes.default.string.isRequired,
mode: _propTypes.default.string,
lineNumbers: _propTypes.default.bool.isRequired,
indentUnit: _propTypes.default.number.isRequired,
indentWithTabs: _propTypes.default.bool.isRequired,
matchBrackets: _propTypes.default.bool.isRequired,
autoCloseBrackets: _propTypes.default.bool.isRequired,
keyMap: _propTypes.default.string.isRequired,
foldOptions: _propTypes.default.object,
dragDrop: _propTypes.default.bool.isRequired,
extraKeys: _propTypes.default.object.isRequired,
readOnly: _propTypes.default.bool.isRequired,
foldGutter: _propTypes.default.bool.isRequired
});
(0, _defineProperty2.default)(CodeMirrorComponent, "defaultProps", {
mode: null,
lineNumbers: true,
indentUnit: 4,
indentWithTabs: true,
matchBrackets: true,
autoCloseBrackets: true,
keyMap: 'default',
dragDrop: false,
extraKeys: {},
readOnly: false,
foldGutter: false
});