slate-edit-code
Version:
A Slate plugin to handle code blocks editing.
1,770 lines (1,303 loc) • 1.62 MB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
/* eslint-disable import/no-extraneous-dependencies */
/* global document */
var _react = require('react');
var React = _interopRequireWildcard(_react);
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
var _slateReact = require('slate-react');
var _lib = require('../lib/');
var _lib2 = _interopRequireDefault(_lib);
var _value = require('./value');
var _value2 = _interopRequireDefault(_value);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var plugin = (0, _lib2.default)();
var plugins = [plugin];
function renderNode(props) {
var node = props.node,
children = props.children,
attributes = props.attributes;
switch (node.type) {
case 'code_block':
return React.createElement(
'div',
_extends({ className: 'code' }, attributes),
children
);
case 'code_line':
return React.createElement(
'pre',
attributes,
children
);
case 'paragraph':
return React.createElement(
'p',
attributes,
children
);
case 'heading':
return React.createElement(
'h1',
attributes,
children
);
default:
return null;
}
}
var Example = function (_React$Component) {
_inherits(Example, _React$Component);
function Example() {
var _ref;
var _temp, _this, _ret;
_classCallCheck(this, Example);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Example.__proto__ || Object.getPrototypeOf(Example)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
value: _value2.default
}, _this.onChange = function (_ref2) {
var value = _ref2.value;
_this.setState({
value: value
});
}, _this.onToggleCode = function () {
var value = _this.state.value;
_this.onChange(plugin.changes.toggleCodeBlock(value.change(), 'paragraph').focus());
}, _temp), _possibleConstructorReturn(_this, _ret);
}
_createClass(Example, [{
key: 'render',
value: function render() {
var value = this.state.value;
return React.createElement(
'div',
null,
React.createElement(
'button',
{ onClick: this.onToggleCode },
plugin.utils.isInCodeBlock(value) ? 'Paragraph' : 'Code Block'
),
React.createElement(_slateReact.Editor, {
placeholder: 'Enter some text...',
plugins: plugins,
value: value,
onChange: this.onChange,
renderNode: renderNode
})
);
}
}]);
return Example;
}(React.Component);
// $FlowFixMe
_reactDom2.default.render(React.createElement(Example, null), document.getElementById('example'));
},{"../lib/":21,"./value":2,"react":403,"react-dom":250,"slate-react":411}],2:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slateHyperscript = require('slate-hyperscript');
var h = (0, _slateHyperscript.createHyperscript)({
blocks: {
heading: 'heading',
paragraph: 'paragraph',
code_block: 'code_block',
code_line: 'code_line'
}
}); /** @jsx h */
// eslint-disable-next-line
var value = h(
'value',
null,
h(
'document',
null,
h(
'heading',
null,
'Slate + Code Editing'
),
h(
'paragraph',
null,
'This page is a basic example of Slate + slate-edit-code plugin. Press Tab to indent code. Shift+Tab to unindent. Press Enter to carry indentation onto the newline. Press Mod (Cmd on Mac, Ctrl on Windows) + Enter to exit the code block.'
),
h(
'code_block',
null,
h(
'code_line',
null,
'// Some JavaScript'
),
h(
'code_line',
null,
'function hello() {'
),
h(
'code_line',
null,
" console.log('Hello World')"
),
h(
'code_line',
null,
'}'
)
),
h(
'paragraph',
null,
'End paragraph'
)
)
);
exports.default = value;
},{"slate-hyperscript":408}],3:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
/**
* Dedent all lines in selection
*/
function dedentLines(opts, change,
// Indent to remove
indent) {
var value = change.value;
var document = value.document,
selection = value.selection;
var lines = document.getBlocksAtRange(selection).filter(function (node) {
return node.type === opts.lineType;
});
return lines.reduce(function (c, line) {
// Remove a level of indent from the start of line
var text = line.nodes.first();
var lengthToRemove = text.characters.takeWhile(function (char, index) {
return indent.charAt(index) === char.text;
}).count();
return c.removeTextByKey(text.key, 0, lengthToRemove);
}, change);
}
exports.default = dedentLines;
},{"slate":428}],4:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
/**
* Indent all lines in selection
*/
function indentLines(opts, change,
// Indent to add
indent) {
var value = change.value;
var document = value.document,
selection = value.selection;
var lines = document.getBlocksAtRange(selection).filter(function (node) {
return node.type === opts.lineType;
});
return lines.reduce(function (c, line) {
// Insert an indent at start of line
var text = line.nodes.first();
return c.insertTextByKey(text.key, 0, indent);
}, change);
}
exports.default = indentLines;
},{"slate":428}],5:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.wrapCodeBlockByKey = exports.wrapCodeBlock = exports.unwrapCodeBlockByKey = exports.unwrapCodeBlock = exports.toggleCodeBlock = exports.indentLines = exports.dedentLines = undefined;
var _dedentLines = require('./dedentLines');
var _dedentLines2 = _interopRequireDefault(_dedentLines);
var _indentLines = require('./indentLines');
var _indentLines2 = _interopRequireDefault(_indentLines);
var _toggleCodeBlock = require('./toggleCodeBlock');
var _toggleCodeBlock2 = _interopRequireDefault(_toggleCodeBlock);
var _unwrapCodeBlock = require('./unwrapCodeBlock');
var _unwrapCodeBlock2 = _interopRequireDefault(_unwrapCodeBlock);
var _unwrapCodeBlockByKey = require('./unwrapCodeBlockByKey');
var _unwrapCodeBlockByKey2 = _interopRequireDefault(_unwrapCodeBlockByKey);
var _wrapCodeBlock = require('./wrapCodeBlock');
var _wrapCodeBlock2 = _interopRequireDefault(_wrapCodeBlock);
var _wrapCodeBlockByKey = require('./wrapCodeBlockByKey');
var _wrapCodeBlockByKey2 = _interopRequireDefault(_wrapCodeBlockByKey);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.dedentLines = _dedentLines2.default;
exports.indentLines = _indentLines2.default;
exports.toggleCodeBlock = _toggleCodeBlock2.default;
exports.unwrapCodeBlock = _unwrapCodeBlock2.default;
exports.unwrapCodeBlockByKey = _unwrapCodeBlockByKey2.default;
exports.wrapCodeBlock = _wrapCodeBlock2.default;
exports.wrapCodeBlockByKey = _wrapCodeBlockByKey2.default;
},{"./dedentLines":3,"./indentLines":4,"./toggleCodeBlock":6,"./unwrapCodeBlock":7,"./unwrapCodeBlockByKey":8,"./wrapCodeBlock":9,"./wrapCodeBlockByKey":10}],6:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _utils = require('../utils');
var _wrapCodeBlock = require('./wrapCodeBlock');
var _wrapCodeBlock2 = _interopRequireDefault(_wrapCodeBlock);
var _unwrapCodeBlock = require('./unwrapCodeBlock');
var _unwrapCodeBlock2 = _interopRequireDefault(_unwrapCodeBlock);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Toggle code block / paragraph.
*/
function toggleCodeBlock(opts, change,
// When toggling a code block off, type to convert to
type) {
if ((0, _utils.isInCodeBlock)(opts, change.value)) {
return (0, _unwrapCodeBlock2.default)(opts, change, type);
}
return (0, _wrapCodeBlock2.default)(opts, change);
}
exports.default = toggleCodeBlock;
},{"../utils":27,"./unwrapCodeBlock":7,"./wrapCodeBlock":9,"slate":428}],7:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _utils = require('../utils');
var _unwrapCodeBlockByKey = require('./unwrapCodeBlockByKey');
var _unwrapCodeBlockByKey2 = _interopRequireDefault(_unwrapCodeBlockByKey);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Convert a code block to a normal block.
*/
function unwrapCodeBlock(opts, change, type) {
var value = change.value;
var codeBlock = (0, _utils.getCurrentCode)(opts, value);
if (!codeBlock) {
return change;
}
// Convert to paragraph
(0, _unwrapCodeBlockByKey2.default)(opts, change, codeBlock.key, type);
return change;
}
exports.default = unwrapCodeBlock;
},{"../utils":27,"./unwrapCodeBlockByKey":8,"slate":428}],8:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
/**
* Unwrap a code block into a normal block.
*/
function unwrapCodeBlockByKey(opts, change, key, type) {
var value = change.value;
var document = value.document;
// Get the code block
var codeBlock = document.getDescendant(key);
if (!codeBlock || codeBlock.type != opts.containerType) {
throw new Error('Block passed to unwrapCodeBlockByKey should be a code block container');
}
// change lines into paragraph
codeBlock.nodes.forEach(function (line) {
return change.setNodeByKey(line.key, { type: type }, { normalize: false }).unwrapNodeByKey(line.key, { normalize: false });
});
return change;
}
exports.default = unwrapCodeBlockByKey;
},{"slate":428}],9:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _wrapCodeBlockByKey = require('./wrapCodeBlockByKey');
var _wrapCodeBlockByKey2 = _interopRequireDefault(_wrapCodeBlockByKey);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Wrap current block into a code block.
*/
function wrapCodeBlock(opts, change) {
var value = change.value;
var startBlock = value.startBlock,
selection = value.selection;
// Convert to code block
(0, _wrapCodeBlockByKey2.default)(opts, change, startBlock.key);
// Move selection back in the block
change.collapseToStartOf(change.value.document.getDescendant(startBlock.key)).moveOffsetsTo(selection.startOffset);
return change;
}
exports.default = wrapCodeBlock;
},{"./wrapCodeBlockByKey":10,"slate":428}],10:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _utils = require('../utils');
/**
* Wrap a block into a code block.
*/
function wrapCodeBlockByKey(opts, change, key) {
var value = change.value;
var document = value.document;
var startBlock = document.getDescendant(key);
var text = startBlock.text;
// Remove all child
startBlock.nodes.forEach(function (node) {
change.removeNodeByKey(node.key, { normalize: false });
});
// Insert new text
var toInsert = (0, _utils.deserializeCode)(opts, text);
toInsert.nodes.forEach(function (node, i) {
change.insertNodeByKey(startBlock.key, i, node, { normalize: false });
});
// Set node type
change.setNodeByKey(startBlock.key, {
type: opts.containerType
});
return change;
}
exports.default = wrapCodeBlockByKey;
},{"../utils":27,"slate":428}],11:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _options = require('./options');
var _options2 = _interopRequireDefault(_options);
var _utils = require('./utils');
var _changes = require('./changes');
var _validation = require('./validation');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* The core of the plugin, which does not relies on `slate-react`, and includes
* everything but behavior and rendering logic.
*/
function core(optsParam) {
var opts = new _options2.default(optsParam);
return {
schema: (0, _validation.schema)(opts),
changes: {
unwrapCodeBlockByKey: _changes.unwrapCodeBlockByKey.bind(null, opts),
wrapCodeBlockByKey: _changes.wrapCodeBlockByKey.bind(null, opts),
wrapCodeBlock: _changes.wrapCodeBlock.bind(null, opts),
unwrapCodeBlock: _changes.unwrapCodeBlock.bind(null, opts),
toggleCodeBlock: _changes.toggleCodeBlock.bind(null, opts)
},
utils: {
isInCodeBlock: _utils.isInCodeBlock.bind(null, opts),
deserializeCode: _utils.deserializeCode.bind(null, opts)
}
};
}
exports.default = core;
},{"./changes":5,"./options":22,"./utils":27,"./validation":29}],12:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.onKeyDown = exports.onPaste = exports.onSelectAll = exports.onBackspace = exports.onModEnter = exports.onEnter = exports.onShiftTab = exports.onTab = undefined;
var _onTab = require('./onTab');
var _onTab2 = _interopRequireDefault(_onTab);
var _onShiftTab = require('./onShiftTab');
var _onShiftTab2 = _interopRequireDefault(_onShiftTab);
var _onEnter = require('./onEnter');
var _onEnter2 = _interopRequireDefault(_onEnter);
var _onModEnter = require('./onModEnter');
var _onModEnter2 = _interopRequireDefault(_onModEnter);
var _onBackspace = require('./onBackspace');
var _onBackspace2 = _interopRequireDefault(_onBackspace);
var _onSelectAll = require('./onSelectAll');
var _onSelectAll2 = _interopRequireDefault(_onSelectAll);
var _onPaste = require('./onPaste');
var _onPaste2 = _interopRequireDefault(_onPaste);
var _onKeyDown = require('./onKeyDown');
var _onKeyDown2 = _interopRequireDefault(_onKeyDown);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.onTab = _onTab2.default;
exports.onShiftTab = _onShiftTab2.default;
exports.onEnter = _onEnter2.default;
exports.onModEnter = _onModEnter2.default;
exports.onBackspace = _onBackspace2.default;
exports.onSelectAll = _onSelectAll2.default;
exports.onPaste = _onPaste2.default;
exports.onKeyDown = _onKeyDown2.default;
},{"./onBackspace":13,"./onEnter":14,"./onKeyDown":15,"./onModEnter":16,"./onPaste":17,"./onSelectAll":18,"./onShiftTab":19,"./onTab":20}],13:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _endsWith = require('ends-with');
var _endsWith2 = _interopRequireDefault(_endsWith);
var _utils = require('../utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* User pressed Delete in an editor:
* Remove last idnentation before cursor
*/
function onBackspace(opts, event, change, editor) {
var value = change.value;
if (value.isExpanded) {
return undefined;
}
var startOffset = value.startOffset,
startText = value.startText;
var currentLine = value.startBlock;
// Detect and remove indentation at cursor
var indent = (0, _utils.getCurrentIndent)(opts, value);
var beforeSelection = currentLine.text.slice(0, startOffset);
// If the line before selection ending with the indentation?
if ((0, _endsWith2.default)(beforeSelection, indent)) {
// Remove indent
event.preventDefault();
return change.deleteBackward(indent.length).focus();
} else if (opts.exitBlockType) {
// Otherwise check if we are in an empty code container...
var currentCode = (0, _utils.getCurrentCode)(opts, value);
var isStartOfCode = startOffset === 0 && currentCode.getFirstText() === startText;
// PERF: avoid checking for whole currentCode.text
var isEmpty = currentCode.nodes.size === 1 && currentLine.text.length === 0;
if (isStartOfCode && isEmpty) {
event.preventDefault();
// Convert it to default exit type
return change.setBlocks(opts.exitBlockType, { normalize: false }).unwrapNodeByKey(currentLine.key);
}
}
return undefined;
}
exports.default = onBackspace;
},{"../utils":27,"ends-with":34,"slate":428}],14:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _utils = require('../utils');
/**
* User pressed Enter in an editor:
* Insert a new code line and start it with the indentation from previous line
*/
function onEnter(opts, event, change, editor) {
var value = change.value;
if (!value.isCollapsed) {
return undefined;
}
event.preventDefault();
var startBlock = value.startBlock;
var currentLineText = startBlock.text;
var indent = (0, _utils.getIndent)(currentLineText, '');
return change.splitBlock().insertText(indent).focus();
}
exports.default = onEnter;
},{"../utils":27,"slate":428}],15:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _isHotkey = require('is-hotkey');
require('slate');
var _utils = require('../utils');
var _onTab = require('./onTab');
var _onTab2 = _interopRequireDefault(_onTab);
var _onShiftTab = require('./onShiftTab');
var _onShiftTab2 = _interopRequireDefault(_onShiftTab);
var _onEnter = require('./onEnter');
var _onEnter2 = _interopRequireDefault(_onEnter);
var _onModEnter = require('./onModEnter');
var _onModEnter2 = _interopRequireDefault(_onModEnter);
var _onBackspace = require('./onBackspace');
var _onBackspace2 = _interopRequireDefault(_onBackspace);
var _onSelectAll = require('./onSelectAll');
var _onSelectAll2 = _interopRequireDefault(_onSelectAll);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var isModA = (0, _isHotkey.isKeyHotkey)('mod+a');
var isShiftTab = (0, _isHotkey.isKeyHotkey)('shift+tab');
var isTab = (0, _isHotkey.isKeyHotkey)('tab');
var isModEnter = (0, _isHotkey.isKeyHotkey)('mod+enter');
var isEnter = (0, _isHotkey.isKeyHotkey)('enter');
var isBackspace = (0, _isHotkey.isKeyHotkey)('backspace');
/**
* User is pressing a key in the editor
*/
function onKeyDown(opts, event, change, editor) {
var value = change.value;
var currentCode = (0, _utils.getCurrentCode)(opts, value);
// Inside code ?
if (!currentCode) {
return undefined;
}
// Add opts in the argument list
var args = [opts, event, change, editor];
// Select all the code in the block (Mod+a)
if (opts.selectAll && isModA(event)) {
return _onSelectAll2.default.apply(undefined, args);
} else if (isShiftTab(event)) {
// User is pressing Shift+Tab
return _onShiftTab2.default.apply(undefined, args);
} else if (isTab(event)) {
// User is pressing Tab
return _onTab2.default.apply(undefined, args);
} else if (opts.exitBlockType && isModEnter(event)) {
// User is pressing Mod+Enter
return _onModEnter2.default.apply(undefined, args);
} else if (isEnter(event)) {
// User is pressing Enter
return _onEnter2.default.apply(undefined, args);
} else if (isBackspace(event)) {
// User is pressing Backspace
return _onBackspace2.default.apply(undefined, args);
}
return undefined;
}
exports.default = onKeyDown;
},{"../utils":27,"./onBackspace":13,"./onEnter":14,"./onModEnter":16,"./onSelectAll":18,"./onShiftTab":19,"./onTab":20,"is-hotkey":65,"slate":428}],16:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
/**
* User pressed Mod+Enter in an editor
* Exit the current code block
*/
function onModEnter(opts, event, change, editor) {
var value = change.value;
if (!value.isCollapsed) {
return undefined;
}
event.preventDefault();
// Exit the code block
return opts.resolvedOnExit(change);
}
exports.default = onModEnter;
},{"slate":428}],17:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slate = require('slate');
var _slateReact = require('slate-react');
var _utils = require('../utils');
/**
* User is pasting content, insert it as text
*/
function onPaste(opts, event, change, editor) {
var value = change.value;
var data = (0, _slateReact.getEventTransfer)(event);
var currentCode = (0, _utils.getCurrentCode)(opts, value);
// Only handle paste when selection is completely a code block
var endBlock = value.endBlock;
if (!currentCode || !currentCode.hasDescendant(endBlock.key)) {
return undefined;
}
// Convert to text if needed
var text = void 0;
if (data.type === 'fragment') {
text = data.fragment.getTexts().map(function (t) {
return t.text;
}).join('\n');
} else {
text = data.text;
}
// Convert the text to code lines
var lines = (0, _utils.deserializeCode)(opts, text).nodes;
var fragment = _slate.Document.create({ nodes: lines });
return change.insertFragment(fragment);
}
exports.default = onPaste;
},{"../utils":27,"slate":428,"slate-react":411}],18:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _utils = require('../utils');
/**
* User is Cmd+A to select all text
*/
function onSelectAll(opts, event, change, editor) {
var value = change.value;
event.preventDefault();
var currentCode = (0, _utils.getCurrentCode)(opts, value);
return change.collapseToStartOf(currentCode.getFirstText()).extendToEndOf(currentCode.getLastText());
}
exports.default = onSelectAll;
},{"../utils":27,"slate":428}],19:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _utils = require('../utils');
var _changes = require('../changes');
/**
* User pressed Shift+Tab in an editor:
* Reduce indentation in the selected lines.
*/
function onShiftTab(opts, event, change, editor) {
var value = change.value;
event.preventDefault();
event.stopPropagation();
var indent = (0, _utils.getCurrentIndent)(opts, value);
// We dedent all selected lines
return (0, _changes.dedentLines)(opts, change, indent);
}
exports.default = onShiftTab;
},{"../changes":5,"../utils":27,"slate":428}],20:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _utils = require('../utils');
var _changes = require('../changes');
/**
* User pressed Tab in an editor:
* Insert a tab after detecting it from code block content.
*/
function onTab(opts, event, change, editor) {
var value = change.value;
event.preventDefault();
event.stopPropagation();
var isCollapsed = value.isCollapsed;
var indent = (0, _utils.getCurrentIndent)(opts, value);
// Selection is collapsed, we just insert an indent at cursor
if (isCollapsed) {
return change.insertText(indent).focus();
}
// We indent all selected lines
return (0, _changes.indentLines)(opts, change, indent);
}
exports.default = onTab;
},{"../changes":5,"../utils":27,"slate":428}],21:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _options = require('./options');
var _options2 = _interopRequireDefault(_options);
var _handlers = require('./handlers');
var _core = require('./core');
var _core2 = _interopRequireDefault(_core);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* A Slate plugin to handle keyboard events in code blocks.
*/
function EditCode() {
var optsParam = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var opts = new _options2.default(optsParam);
var corePlugin = (0, _core2.default)(opts);
return _extends({}, corePlugin, {
onKeyDown: _handlers.onKeyDown.bind(null, opts),
onPaste: _handlers.onPaste.bind(null, opts)
});
}
exports.default = EditCode;
},{"./core":11,"./handlers":12,"./options":22}],22:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _slate = require('slate');
var _immutable = require('immutable');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var DEFAULTS = {
containerType: 'code_block',
lineType: 'code_line',
exitBlockType: 'paragraph',
selectAll: true,
allowMarks: false,
getIndent: null,
onExit: null
};
/**
* The plugin options container
*/
var Options = function (_Record) {
_inherits(Options, _Record);
function Options() {
_classCallCheck(this, Options);
return _possibleConstructorReturn(this, (Options.__proto__ || Object.getPrototypeOf(Options)).apply(this, arguments));
}
_createClass(Options, [{
key: 'resolvedOnExit',
value: function resolvedOnExit(change) {
if (this.onExit) {
// Custom onExit option
return this.onExit(change);
}
// Default behavior: insert an exit block
var range = change.value.selection;
var exitBlock = _slate.Block.create({
type: this.exitBlockType,
nodes: [_slate.Text.create()]
});
change.deleteAtRange(range, { normalize: false });
change.insertBlockAtRange(change.value.selection, exitBlock, {
normalize: false
});
// Exit the code block
change.unwrapNodeByKey(exitBlock.key);
return change.collapseToStartOf(exitBlock);
}
}]);
return Options;
}((0, _immutable.Record)(DEFAULTS));
exports.default = Options;
},{"immutable":62,"slate":428}],23:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slate = require('slate');
var _immutable = require('immutable');
var _detectNewline = require('detect-newline');
var _detectNewline2 = _interopRequireDefault(_detectNewline);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var DEFAULT_NEWLINE = '\n';
/**
* Deserialize a text into a code block
*/
function deserializeCode(opts, text) {
var sep = (0, _detectNewline2.default)(text) || DEFAULT_NEWLINE;
var lines = (0, _immutable.List)(text.split(sep)).map(function (line) {
return _slate.Block.create({
type: opts.lineType,
nodes: [_slate.Text.create(line)]
});
});
var code = _slate.Block.create({
type: opts.containerType,
nodes: lines
});
return code;
}
exports.default = deserializeCode;
},{"detect-newline":32,"immutable":62,"slate":428}],24:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
/**
* Return the current code block, from current selection or from a node key.
*/
function getCurrentCode(opts, value, key) {
var document = value.document;
var currentBlock = void 0;
if (key) {
currentBlock = value.document.getDescendant(key);
} else {
if (!value.selection.startKey) return null;
currentBlock = value.startBlock;
}
// The structure is always code_block -> code_line -> text
// So the parent of the currentBlock should be the code_block
var parent = document.getParent(currentBlock.key);
if (parent && parent.type === opts.containerType) {
return parent;
}
return null;
}
exports.default = getCurrentCode;
},{"slate":428}],25:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
var _getIndent = require('./getIndent');
var _getIndent2 = _interopRequireDefault(_getIndent);
var _getCurrentCode = require('./getCurrentCode');
var _getCurrentCode2 = _interopRequireDefault(_getCurrentCode);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Detect indentation in the current code block
*/
function getCurrentIndent(opts, value) {
if (opts.getIndent) {
return opts.getIndent(value);
}
var currentCode = (0, _getCurrentCode2.default)(opts, value);
if (!currentCode) {
return '';
}
var text = currentCode.getTexts().map(function (t) {
return t.text;
}).join('\n');
return (0, _getIndent2.default)(text);
}
exports.default = getCurrentIndent;
},{"./getCurrentCode":24,"./getIndent":26,"slate":428}],26:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _detectIndent = require('detect-indent');
var _detectIndent2 = _interopRequireDefault(_detectIndent);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var DEFAULT_INDENTATION = ' ';
/**
* Detect indentation in a text
*/
function getIndent(text) {
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_INDENTATION;
return (0, _detectIndent2.default)(text).indent || defaultValue;
}
exports.default = getIndent;
},{"detect-indent":31}],27:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isInCodeBlock = exports.getIndent = exports.getCurrentIndent = exports.getCurrentCode = exports.deserializeCode = undefined;
var _deserializeCode = require('./deserializeCode');
var _deserializeCode2 = _interopRequireDefault(_deserializeCode);
var _getCurrentCode = require('./getCurrentCode');
var _getCurrentCode2 = _interopRequireDefault(_getCurrentCode);
var _getCurrentIndent = require('./getCurrentIndent');
var _getCurrentIndent2 = _interopRequireDefault(_getCurrentIndent);
var _getIndent = require('./getIndent');
var _getIndent2 = _interopRequireDefault(_getIndent);
var _isInCodeBlock = require('./isInCodeBlock');
var _isInCodeBlock2 = _interopRequireDefault(_isInCodeBlock);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.deserializeCode = _deserializeCode2.default;
exports.getCurrentCode = _getCurrentCode2.default;
exports.getCurrentIndent = _getCurrentIndent2.default;
exports.getIndent = _getIndent2.default;
exports.isInCodeBlock = _isInCodeBlock2.default;
},{"./deserializeCode":23,"./getCurrentCode":24,"./getCurrentIndent":25,"./getIndent":26,"./isInCodeBlock":28}],28:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
require('slate');
/**
* Test if current selection is in a code block.
*/
function isInCodeBlock(opts, value) {
var document = value.document,
startKey = value.startKey;
var codeBlock = document.getClosest(startKey, function (block) {
return block.type === opts.containerType;
});
return Boolean(codeBlock);
}
exports.default = isInCodeBlock;
},{"slate":428}],29:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.schema = undefined;
var _schema = require('./schema');
var _schema2 = _interopRequireDefault(_schema);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.schema = _schema2.default;
},{"./schema":30}],30:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slate = require('slate');
var _slateSchemaViolations = require('slate-schema-violations');
var _immutable = require('immutable');
var _utils = require('../utils');
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* Create a schema definition with rules to normalize code blocks
*/
function schema(opts) {
var _blocks;
var baseSchema = {
blocks: (_blocks = {}, _defineProperty(_blocks, opts.containerType, {
nodes: [{ types: [opts.lineType] }],
normalize: function normalize(change, violation, context) {
switch (violation) {
case _slateSchemaViolations.CHILD_TYPE_INVALID:
return onlyLine(opts, change, context);
default:
return undefined;
}
}
}), _defineProperty(_blocks, opts.lineType, {
nodes: [{ objects: ['text'], min: 1 }],
parent: { types: [opts.containerType] },
normalize: function normalize(change, violation, context) {
switch (violation) {
case _slateSchemaViolations.PARENT_TYPE_INVALID:
return noOrphanLine(opts, change, context);
default:
return undefined;
}
}
}), _blocks)
};
if (!opts.allowMarks) {
baseSchema.blocks[opts.lineType].marks = [];
}
return baseSchema;
}
/**
* A rule that ensure code blocks only contain lines of code, and no marks
*/
function onlyLine(opts, change, context) {
return change.withoutNormalization(function (c) {
var codeLines = (0, _immutable.List)();
context.node.nodes.forEach(function (node) {
if (node.object === opts.lineType) {
return;
}
if (node.object === 'text') {
if (node.text.length === 0) {
return;
}
codeLines = codeLines.concat((0, _utils.deserializeCode)(opts, node.text).nodes);
}
c.removeNodeByKey(node.key);
});
codeLines.forEach(function (codeLine, index) {
c.insertNodeByKey(context.node.key, index, codeLine);
});
return c;
});
}
/**
* Return a list of group of code lines. Used to wrap them together in
* independent code blocks.
*/
function getSuccessiveCodeLines(opts, nodes) {
var isLine = function isLine(n) {
return n.type === opts.lineType;
};
var nonLines = nodes.takeUntil(isLine);
var afterNonLines = nodes.skip(nonLines.size);
if (afterNonLines.isEmpty()) {
return (0, _immutable.List)();
}
var firstGroup = afterNonLines.takeWhile(isLine);
var restOfNodes = afterNonLines.skip(firstGroup.size);
return (0, _immutable.List)([firstGroup]).concat(getSuccessiveCodeLines(opts, restOfNodes));
}
/**
* A rule that ensure code lines are always children
* of a code block.
*/
function noOrphanLine(opts, change, context) {
var parent = context.parent;
var linesGroup = getSuccessiveCodeLines(opts, parent.nodes);
linesGroup.forEach(function (group) {
var container = _slate.Block.create({ type: opts.containerType, nodes: [] });
var firstLineIndex = parent.nodes.indexOf(group.first());
change.insertNodeByKey(parent.key, firstLineIndex, container, {
normalize: false
});
group.forEach(function (line, index) {
return change.moveNodeByKey(line.key, container.key, index, {
normalize: false
});
});
});
}
exports.default = schema;
},{"../utils":27,"immutable":62,"slate":428,"slate-schema-violations":427}],31:[function(require,module,exports){
/* eslint-disable guard-for-in */
'use strict';
var repeating = require('repeating');
// detect either spaces or tabs but not both to properly handle tabs
// for indentation and spaces for alignment
var INDENT_RE = /^(?:( )+|\t+)/;
function getMostUsed(indents) {
var result = 0;
var maxUsed = 0;
var maxWeight = 0;
for (var n in indents) {
var indent = indents[n];
var u = indent[0];
var w = indent[1];
if (u > maxUsed || u === maxUsed && w > maxWeight) {
maxUsed = u;
maxWeight = w;
result = Number(n);
}
}
return result;
}
module.exports = function (str) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
// used to see if tabs or spaces are the most used
var tabs = 0;
var spaces = 0;
// remember the size of previous line's indentation
var prev = 0;
// remember how many indents/unindents as occurred for a given size
// and how much lines follow a given indentation
//
// indents = {
// 3: [1, 0],
// 4: [1, 5],
// 5: [1, 0],
// 12: [1, 0],
// }
var indents = {};
// pointer to the array of last used indent
var current;
// whether the last action was an indent (opposed to an unindent)
var isIndent;
str.split(/\n/g).forEach(function (line) {
if (!line) {
// ignore empty lines
return;
}
var indent;
var matches = line.match(INDENT_RE);
if (!matches) {
indent = 0;
} else {
indent = matches[0].length;
if (matches[1]) {
spaces++;
} else {
tabs++;
}
}
var diff = indent - prev;
prev = indent;
if (diff) {
// an indent or unindent has been detected
isIndent = diff > 0;
current = indents[isIndent ? diff : -diff];
if (current) {
current[0]++;
} else {
current = indents[diff] = [1, 0];
}
} else if (current) {
// if the last action was an indent, increment the weight
current[1] += Number(isIndent);
}
});
var amount = getMostUsed(indents);
var type;
var actual;
if (!amount) {
type = null;
actual = '';
} else if (spaces >= tabs) {
type = 'space';
actual = repeating(' ', amount);
} else {
type = 'tab';
actual = repeating('\t', amount);
}
return {
amount: amount,
type: type,
indent: actual
};
};
},{"repeating":404}],32:[function(require,module,exports){
'use strict';
module.exports = function (str) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
var newlines = (str.match(/(?:\r?\n)/g) || []);
if (newlines.length === 0) {
return null;
}
var crlf = newlines.filter(function (el) {
return el === '\r\n';
}).length;
var lf = newlines.length - crlf;
return crlf > lf ? '\r\n' : '\n';
};
module.exports.graceful = function (str) {
return module.exports(str) || '\n';
};
},{}],33:[function(require,module,exports){
'use strict';
var GROUP_LEFT_TO_RIGHT,
GROUP_RIGHT_TO_LEFT,
EXPRESSION_LEFT_TO_RIGHT,
EXPRESSION_RIGHT_TO_LEFT;
/*
* Character ranges of left-to-right characters.
*/
GROUP_LEFT_TO_RIGHT = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6' +
'\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u200E\u2C00-\uFB1C' +
'\uFE00-\uFE6F\uFEFD-\uFFFF';
/*
* Character ranges of right-to-left characters.
*/
GROUP_RIGHT_TO_LEFT = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC';
/*
* Expression to match a left-to-right string.
*
* Matches the start of a string, followed by zero or
* more non-right-to-left characters, followed by a
* left-to-right character.
*/
EXPRESSION_LEFT_TO_RIGHT = new RegExp(
'^[^' + GROUP_RIGHT_TO_LEFT + ']*[' + GROUP_LEFT_TO_RIGHT + ']'
);
/*
* Expression to match a right-to-left string.
*
* Matches the start of a string, followed by zero or
* more non-left-to-right characters, followed by a
* right-to-left character.
*/
EXPRESSION_RIGHT_TO_LEFT = new RegExp(
'^[^' + GROUP_LEFT_TO_RIGHT + ']*[' + GROUP_RIGHT_TO_LEFT + ']'
);
/**
* Detect the direction of text.
*
* @param {string} value - value to stringify and check.
* @return {string} - One of `"rtl"`, `"ltr"`, or
* `"neutral"`.
*/
function direction(value) {
value = value.toString();
if (EXPRESSION_RIGHT_TO_LEFT.test(value)) {
return 'rtl';
}
if (EXPRESSION_LEFT_TO_RIGHT.test(value)) {
return 'ltr';
}
return 'neutral';
}
/*
* Expose `direction`.
*/
module.exports = direction;
},{}],34:[function(require,module,exports){
/*!
* ends-with <https://github.com/jonschlinkert/ends-with>
*
* Copyright (c) 2014 Jon Schlinkert, contributors.
* Licensed under the MIT license.
*/
'use strict';
module.exports = function (a, b) {
if (Array.isArray(a)) {
return a[a.length - 1] === b;
}
a = String(a);
b = String(b);
var i = b.length;
var len = a.length - i;
while (i--) {
if (b.charAt(i) !== a.charAt(len + i)) {
return false;
}
}
return true;
};
},{}],35:[function(require,module,exports){
(function (global){
/*! https://mths.be/esrever v0.2.0 by @mathias */
;(function(root) {
// Detect free variables `exports`
var freeExports = typeof exports == 'object' && exports;
// Detect free variable `module`
var freeModule = typeof module == 'object' && module &&
module.exports == freeExports && module;
// Detect free variable `global`, from Node.js or Browserified code,
// and use it as `root`
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
/*--------------------------------------------------------------------------*/
var regexSymbolWithCombiningMarks = /([\0-\u02FF\u0370-\u1AAF\u1B00-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uE000-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])([\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g;
var regexSurrogatePair = /([\uD800-\uDBFF])([\uDC00-\uDFFF])/g;
var reverse = function(string) {
// Step 1: deal with combining marks and astral symbols (surrogate pairs)
string = string
// Swap symbols with their combining marks so the combining marks go first
.replace(regexSymbolWithCombiningMarks, function($0, $1, $2) {
// Reverse the combining marks so they will end up in the same order
// later on (after another round of reversing)
return reverse($2) + $1;
})
// Swap high and low surrogates so the low surrogates go first
.replace(regexSurrogatePair, '$2$1');
// Step 2: reverse the code units in the string
var result = '';
var index = string.length;
while (index--) {
result += string.charAt(index);
}
return result;
};
/*--------------------------------------------------------------------------*/
var esrever = {
'version': '0.2.0',
'reverse': reverse
};
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define.amd == 'object' &&
define.amd
) {
define(function() {
return esrever;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js, io.js, or RingoJS v0.8.0+
freeModule.exports = esrever;
} else { // in Narwhal or RingoJS v0.7.0-
for (var key in esrever) {
esrever.hasOwnProperty(key) && (freeExports[key] = esrever[key]);
}
}
} else { // in Rhino or a web browser
root.esrever = esrever;
}
}(this));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],36:[function(require,module,exports){
(function (process){
'use strict';
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @typechecks
*/
var emptyFunction = require