UNPKG

slate-edit-list

Version:

A Slate plugin to handle keyboard events in lists.

1,592 lines (1,318 loc) 2.39 MB
(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 _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 React = require('react'); var ReactDOM = require('react-dom'); var Slate = require('slate'); var yaml = require('yaml-js'); var PluginEditList = require('../lib/'); var stateJson = yaml.load(require('./state.yaml')); var plugin = PluginEditList(); var plugins = [plugin]; var highlightedItems = function highlightedItems(props) { var node = props.node, state = props.state; var isCurrentItem = plugin.utils.getItemsAtRange(state).contains(node); return React.createElement( 'li', _extends({ className: isCurrentItem ? 'current-item' : '', title: isCurrentItem ? 'Current Item' : '' }, props.attributes), props.children ); }; // To update the highlighting of nodes inside the selection highlightedItems.suppressShouldComponentUpdate = true; var SCHEMA = { nodes: { ul_list: function ul_list(props) { return React.createElement( 'ul', props.attributes, props.children ); }, ol_list: function ol_list(props) { return React.createElement( 'ol', props.attributes, props.children ); }, list_item: highlightedItems, paragraph: function paragraph(props) { return React.createElement( 'p', props.attributes, props.children ); }, heading: function heading(props) { return React.createElement( 'h1', props.attributes, props.children ); } } }; var Example = React.createClass({ displayName: 'Example', getInitialState: function getInitialState() { return { state: Slate.Raw.deserialize(stateJson, { terse: true }) }; }, onChange: function onChange(state) { this.setState({ state: state }); }, call: function call(transform) { this.setState({ state: this.state.state.transform().call(transform).apply() }); }, renderToolbar: function renderToolbar() { var _this = this; var _plugin$transforms = plugin.transforms, wrapInList = _plugin$transforms.wrapInList, unwrapList = _plugin$transforms.unwrapList, increaseItemDepth = _plugin$transforms.increaseItemDepth, decreaseItemDepth = _plugin$transforms.decreaseItemDepth; var inList = plugin.utils.isSelectionInList(this.state.state); return React.createElement( 'div', null, React.createElement( 'button', { className: inList ? 'active' : '', onClick: function onClick() { return _this.call(inList ? unwrapList : wrapInList); } }, React.createElement('i', { className: 'fa fa-list-ul fa-lg' }) ), React.createElement( 'button', { className: inList ? '' : 'disabled', onClick: function onClick() { return _this.call(decreaseItemDepth); } }, React.createElement('i', { className: 'fa fa-outdent fa-lg' }) ), React.createElement( 'button', { className: inList ? '' : 'disabled', onClick: function onClick() { return _this.call(increaseItemDepth); } }, React.createElement('i', { className: 'fa fa-indent fa-lg' }) ), React.createElement( 'span', { className: 'sep' }, '\xB7' ), React.createElement( 'button', { onClick: function onClick() { return _this.call(wrapInList); } }, 'Wrap in list' ), React.createElement( 'button', { onClick: function onClick() { return _this.call(unwrapList); } }, 'Unwrap from list' ) ); }, render: function render() { return React.createElement( 'div', null, this.renderToolbar(), React.createElement(Slate.Editor, { placeholder: 'Enter some text...', plugins: plugins, state: this.state.state, onChange: this.onChange, schema: SCHEMA }) ); } }); ReactDOM.render(React.createElement(Example, null), document.getElementById('example')); },{"../lib/":9,"./state.yaml":2,"react":333,"react-dom":186,"slate":354,"yaml-js":417}],2:[function(require,module,exports){ module.exports = "nodes:\n- kind: block\n type: heading\n nodes:\n - kind: text\n ranges:\n - text: 'Slate + List Edition'\n- kind: block\n type: paragraph\n nodes:\n - kind: text\n ranges:\n - text: This page is a basic example of Slate + slate-edit-list plugin. Press Enter in a list to create a new list item. Press Enter again to exit and Shift+Enter to create a paragraph in a list. The items at range are detected and highlighted, for demonstration purpose.\n- kind: block\n type: ul_list\n data:\n style:\n listStyleType: disc\n nodes:\n - kind: block\n type: list_item\n nodes:\n - kind: block\n type: paragraph\n nodes:\n - kind: text\n ranges:\n - text: 'First item in the list'\n - kind: block\n type: list_item\n nodes:\n - kind: block\n type: heading\n nodes:\n - kind: text\n ranges:\n - text: 'With blocks:'\n - kind: block\n type: paragraph\n nodes:\n - kind: text\n ranges:\n - text: 'List item can contain blocks'\n - kind: block\n type: list_item\n nodes:\n - kind: block\n type: paragraph\n nodes:\n - kind: text\n ranges:\n - text: 'Third item in the list, with a nested list'\n - kind: block\n type: ol_list\n data:\n style:\n listStyleType: decimal\n nodes:\n - kind: block\n type: list_item\n nodes:\n - kind: block\n type: paragraph\n nodes:\n - kind: text\n ranges:\n - text: 'First item in the nested list'\n - kind: block\n type: list_item\n nodes:\n - kind: block\n type: paragraph\n nodes:\n - kind: text\n ranges:\n - text: 'Second item in the nested list'\n- kind: block\n type: paragraph\n nodes:\n - kind: text\n ranges:\n - text: 'End paragraph'\n"; },{}],3:[function(require,module,exports){ "use strict"; /** * Return the current list item, from current selection or from a node. * * @param {PluginOptions} opts * @param {Slate.State} state * @param {Slate.Block} block? * @return {Slate.Block || Void} */ function getCurrentItem(opts, state, block) { var document = state.document; if (!block) { if (!state.selection.startKey) return null; block = state.startBlock; } var parent = document.getParent(block.key); return parent && parent.type === opts.typeItem ? parent : null; } module.exports = getCurrentItem; },{}],4:[function(require,module,exports){ 'use strict'; var getCurrentItem = require('./getCurrentItem'); var getListForItem = require('./getListForItem'); /** * Return the parent list block, from current selection or from a node (paragraph in a list item). * * @param {PluginOptions} opts * @param {Slate.State} state * @param {Slate.Block} block? * @return {Slate.Block || Void} */ function getCurrentList(opts, state, block) { var item = getCurrentItem(opts, state, block); if (!item) { return null; } return getListForItem(opts, state, item); } module.exports = getCurrentList; },{"./getCurrentItem":3,"./getListForItem":7}],5:[function(require,module,exports){ 'use strict'; var getCurrentItem = require('./getCurrentItem'); /** * Get depth of current block in a document list * * @param {PluginOptions} opts * @param {Slate.State} state * @param {Slate.Block} block? * @return {Number} */ function getItemDepth(opts, state, block) { var document = state.document, startBlock = state.startBlock; block = block || startBlock; var currentItem = getCurrentItem(opts, state, block); if (!currentItem) { return 0; } var list = document.getParent(currentItem.key); return 1 + getItemDepth(opts, state, list); } module.exports = getItemDepth; },{"./getCurrentItem":3}],6:[function(require,module,exports){ 'use strict'; var _require = require('immutable'), List = _require.List; var isList = require('./isList'); var getCurrentItem = require('./getCurrentItem'); /** * Return the list of items at the given range. The returned items are * the highest list item blocks that cover the range. * * @param {PluginOptions} opts * @param {Slate.Node} state * @param {Slate.Selection} [range] * @return {List<Slate.Block>} Empty if no list of items can cover the range */ function getItemsAtRange(opts, state, range) { range = range || state.selection; if (!range.startKey) { return List(); } var document = state.document; var startBlock = document.getClosestBlock(range.startKey); var endBlock = document.getClosestBlock(range.endKey); if (startBlock === endBlock) { var item = getCurrentItem(opts, state, startBlock); return item ? List([item]) : List(); } var ancestor = document.getCommonAncestor(startBlock.key, endBlock.key); if (isList(opts, ancestor)) { var startPath = ancestor.getPath(startBlock.key); var endPath = ancestor.getPath(endBlock.key); return ancestor.nodes.slice(startPath[0], endPath[0] + 1); } else if (ancestor.type === opts.typeItem) { // The ancestor is the highest list item that covers the range return List([ancestor]); } else { // No list of items can cover the range return List(); } } module.exports = getItemsAtRange; },{"./getCurrentItem":3,"./isList":10,"immutable":162}],7:[function(require,module,exports){ 'use strict'; var isList = require('./isList'); /** * Return the parent list block for an item block. * * @param {PluginOptions} opts * @param {Slate.State} state * @param {Slate.Block} item * @return {Slate.Block || Void} */ function getListForItem(opts, state, item) { var document = state.document; var parent = document.getParent(item.key); return parent && isList(opts, parent) ? parent : null; } module.exports = getListForItem; },{"./isList":10}],8:[function(require,module,exports){ 'use strict'; var getCurrentItem = require('./getCurrentItem'); /** * Return the previous item, from current selection or from a node. * * @param {PluginOptions} opts * @param {Slate.State} state * @param {Slate.Block} block? * @return {Slate.Block || Void} */ function getPreviousItem(opts, state, block) { var document = state.document, startBlock = state.startBlock; block = block || startBlock; var currentItem = getCurrentItem(opts, state, block); var previousSibling = document.getPreviousSibling(currentItem.key); if (!previousSibling) { return null; } else if (previousSibling.type === opts.typeItem) { return previousSibling; } else { return null; } } module.exports = getPreviousItem; },{"./getCurrentItem":3}],9:[function(require,module,exports){ 'use strict'; function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var Options = require('./options'); var onEnter = require('./onEnter'); var onTab = require('./onTab'); var onBackspace = require('./onBackspace'); var makeSchema = require('./makeSchema'); var wrapInList = require('./transforms/wrapInList'); var unwrapList = require('./transforms/unwrapList'); var splitListItem = require('./transforms/splitListItem'); var increaseItemDepth = require('./transforms/increaseItemDepth'); var decreaseItemDepth = require('./transforms/decreaseItemDepth'); var getItemDepth = require('./getItemDepth'); var isList = require('./isList'); var isSelectionInList = require('./isSelectionInList'); var getCurrentItem = require('./getCurrentItem'); var getCurrentList = require('./getCurrentList'); var getItemsAtRange = require('./getItemsAtRange'); var getPreviousItem = require('./getPreviousItem'); var KEY_ENTER = 'enter'; var KEY_TAB = 'tab'; var KEY_BACKSPACE = 'backspace'; /** * A Slate plugin to handle keyboard events in lists. * @param {Options} [opts] Options for the plugin * @return {Object} */ function EditList() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; opts = new Options(opts); /** * Bind a transform to be only applied in list */ function bindTransform(fn) { return function (transform) { var state = transform.state; if (!isSelectionInList(opts, state)) { return transform; } for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return fn.apply(undefined, _toConsumableArray([opts, transform].concat(args))); }; } /** * User is pressing a key in the editor */ function onKeyDown(e, data, state) { // Build arguments list var args = [e, data, state, opts]; switch (data.key) { case KEY_ENTER: return onEnter.apply(undefined, args); case KEY_TAB: return onTab.apply(undefined, args); case KEY_BACKSPACE: return onBackspace.apply(undefined, args); } } var schema = makeSchema(opts); return { onKeyDown: onKeyDown, schema: schema, utils: { getCurrentItem: getCurrentItem.bind(null, opts), getCurrentList: getCurrentList.bind(null, opts), getItemDepth: getItemDepth.bind(null, opts), getItemsAtRange: getItemsAtRange.bind(null, opts), getPreviousItem: getPreviousItem.bind(null, opts), isList: isList.bind(null, opts), isSelectionInList: isSelectionInList.bind(null, opts) }, transforms: { decreaseItemDepth: bindTransform(decreaseItemDepth), increaseItemDepth: bindTransform(increaseItemDepth), splitListItem: bindTransform(splitListItem), unwrapList: bindTransform(unwrapList), wrapInList: wrapInList.bind(null, opts) } }; } module.exports = EditList; },{"./getCurrentItem":3,"./getCurrentList":4,"./getItemDepth":5,"./getItemsAtRange":6,"./getPreviousItem":8,"./isList":10,"./isSelectionInList":11,"./makeSchema":12,"./onBackspace":13,"./onEnter":14,"./onTab":15,"./options":16,"./transforms/decreaseItemDepth":17,"./transforms/increaseItemDepth":18,"./transforms/splitListItem":19,"./transforms/unwrapList":20,"./transforms/wrapInList":21}],10:[function(require,module,exports){ "use strict"; /** * @param {PluginOptions} opts Plugin options * @param {Node} node * @return {Boolean} true if the node is a UL or OL */ function isList(opts, node) { return node.type === opts.typeUL || node.type === opts.typeOL; } module.exports = isList; },{}],11:[function(require,module,exports){ 'use strict'; var getItemsAtRange = require('./getItemsAtRange'); /** * @param {PluginOptions} opts Plugin options * @param {Slate.State} state * @return {Boolean} True if selection is inside a list (and can be unwrapped) */ function isSelectionInList(opts, state) { return !getItemsAtRange(opts, state).isEmpty(); } module.exports = isSelectionInList; },{"./getItemsAtRange":6}],12:[function(require,module,exports){ 'use strict'; var Immutable = require('immutable'); var Set = Immutable.Set; /** * Create a schema for lists * @param {String} opts.typeUL The type of unordered lists * @param {String} opts.typeOL The type of ordered lists * @param {String} opts.typeItem The type of list items * @param {String} opts.typeDefault The type of the default block in list items * @return {Object} A schema definition with rules to normalize lists */ function makeSchema(opts) { return { rules: [listsContainOnlyItems(opts), itemsDescendList(opts), // Must be after itemsDescendList itemsContainBlocks(opts)] }; } /** * @param {String} opts.typeUL The type of unordered lists * @param {String} opts.typeOL The type of ordered lists * @param {String} opts.typeItem The type of list items * @return {Object} A rule that ensure lists only contain list * items, and at least one. */ function listsContainOnlyItems(opts) { var isList = matchTypes([opts.typeUL, opts.typeOL]); return { match: isList, validate: function validate(list) { var notItems = list.nodes.filter(function (n) { return n.type !== opts.typeItem; }); if (notItems.isEmpty()) { // Only valid list items return null; } else { // All the non items return { toWrap: notItems }; } }, /** * @param {List<Nodes>} value.toWrap Children to wrap in list */ normalize: function normalize(transform, node, value) { return value.toWrap.reduce(function (tr, _ref) { var key = _ref.key; return tr.wrapBlockByKey(key, opts.typeItem); }, transform); } }; } /** * @param {String} opts.typeUL The type of unordered lists * @param {String} opts.typeOL The type of ordered lists * @param {String} opts.typeItem The type of list items * @return {Object} A rule that ensure list items are always children * of a list block. */ function itemsDescendList(opts) { var isList = matchTypes([opts.typeUL, opts.typeOL]); return { match: function match(node) { return (node.kind === 'block' || node.kind === 'document') && !isList(node); }, validate: function validate(block) { var listItems = block.nodes.filter(function (n) { return n.type === opts.typeItem; }); if (listItems.isEmpty()) { // No orphan list items. All good. return null; } else { // Unwrap the orphan list items return { toUnwrap: listItems }; } }, /** * Unwrap the given blocks * @param {List<Nodes>} value.toUnwrap */ normalize: function normalize(transform, node, value) { return value.toUnwrap.reduce(function (tr, n) { return tr.unwrapBlockByKey(n.key); }, transform); } }; } /** * @param {String} opts.typeItem The type of list items * @param {String} opts.typeDefault The type of the default block in list items * @return {Object} A rule that ensure list items always contain * blocks. */ function itemsContainBlocks(opts) { var isItem = matchTypes([opts.typeItem]); return { match: isItem, validate: function validate(item) { var shouldWrap = item.nodes.some(function (node) { return node.kind !== 'block'; }); return shouldWrap || null; }, /** * Wraps the children nodes in the default block */ normalize: function normalize(transform, node, _) { var noNorm = { normalize: false }; transform = transform.wrapBlockByKey(node.nodes.first().key, opts.typeDefault, noNorm); var wrapper = transform.state.document.getDescendant(node.key).nodes.first(); // Add the remaining items return node.nodes.rest().reduce(function (tr, n, index) { return tr.moveNodeByKey(n.key, wrapper.key, index + 1, noNorm); }, transform); } }; } /** * @param {Array<String>} types * @return {Function} A function that returns true for nodes that * match one of the given types. */ function matchTypes(types) { types = new Set(types); return function (node) { return types.some(function (type) { return type === node.type; }); }; } module.exports = makeSchema; },{"immutable":162}],13:[function(require,module,exports){ 'use strict'; var unwrapList = require('./transforms/unwrapList'); var getCurrentItem = require('./getCurrentItem'); /** * User pressed Delete in an editor */ function onBackspace(event, data, state, opts) { var startOffset = state.startOffset, selection = state.selection; // Only unwrap... // ... with a collapsed selection if (selection.isExpanded) return; // ... when at the beginning of nodes if (startOffset > 0) return; // ... in a list var currentItem = getCurrentItem(opts, state); if (!currentItem) return; // ... more precisely at the beginning of the current item if (!selection.isAtStartOf(currentItem)) return; event.preventDefault(); return unwrapList(opts, state.transform()).apply(); } module.exports = onBackspace; },{"./getCurrentItem":3,"./transforms/unwrapList":20}],14:[function(require,module,exports){ 'use strict'; var unwrapList = require('./transforms/unwrapList'); var splitListItem = require('./transforms/splitListItem'); var decreaseItemDepth = require('./transforms/decreaseItemDepth'); var getCurrentItem = require('./getCurrentItem'); var getItemDepth = require('./getItemDepth'); /** * User pressed Enter in an editor * * Enter in a list item should split the list item * Enter in an empty list item should remove it * Shift+Enter in a list item should make a new line */ function onEnter(event, data, state, opts) { // Pressing Shift+Enter // should split block normally if (data.isShift) { return null; } var currentItem = getCurrentItem(opts, state); // Not in a list if (!currentItem) { return null; } event.preventDefault(); var isEmpty = currentItem.nodes.size <= 1 && currentItem.length === 0; if (isEmpty) { // Block is empty, we exit the list if (getItemDepth(opts, state) > 1) { return decreaseItemDepth(opts, state.transform()).apply(); } else { // Exit list return unwrapList(opts, state.transform()).apply(); } } else { // Split list item return splitListItem(opts, state.transform()).apply(); } } module.exports = onEnter; },{"./getCurrentItem":3,"./getItemDepth":5,"./transforms/decreaseItemDepth":17,"./transforms/splitListItem":19,"./transforms/unwrapList":20}],15:[function(require,module,exports){ 'use strict'; var decreaseItemDepth = require('./transforms/decreaseItemDepth'); var increaseItemDepth = require('./transforms/increaseItemDepth'); var getCurrentItem = require('./getCurrentItem'); /** * User pressed Tab in an editor. * Tab -> Increase item depth if inside a list item * Shift+Tab -> Decrease item depth if inside a list item */ function onTab(event, data, state, opts) { var isCollapsed = state.isCollapsed; if (!isCollapsed || !getCurrentItem(opts, state)) { return; } // Shift+tab reduce depth if (data.isShift) { event.preventDefault(); return decreaseItemDepth(opts, state.transform()).apply(); } // Tab increases depth event.preventDefault(); return increaseItemDepth(opts, state.transform()).apply(); } module.exports = onTab; },{"./getCurrentItem":3,"./transforms/decreaseItemDepth":17,"./transforms/increaseItemDepth":18}],16:[function(require,module,exports){ 'use strict'; 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 _require = require('immutable'), Record = _require.Record; var DEFAULTS = { // The type of the lists typeUL: 'ul_list', // The type of ordered lists typeOL: 'ol_list', // The type of list items typeItem: 'list_item', // The type of default block in items typeDefault: 'paragraph' }; /** * The plugin options */ var Options = function (_ref) { _inherits(Options, _ref); function Options() { _classCallCheck(this, Options); return _possibleConstructorReturn(this, (Options.__proto__ || Object.getPrototypeOf(Options)).apply(this, arguments)); } return Options; }(new Record(DEFAULTS)); module.exports = Options; },{"immutable":162}],17:[function(require,module,exports){ 'use strict'; var Slate = require('slate'); var getItemDepth = require('../getItemDepth'); var getCurrentItem = require('../getCurrentItem'); /** * Decreases the depth of the current item. The following items will * be moved as sublist of the decreased item. * * No-op for root items. * * @param {PluginOptions} opts * @param {Slate.Transform} transform * @return {Transform} transform */ function decreaseItemDepth(opts, transform, ordered) { var _transform = transform, state = _transform.state; var document = state.document; // Cannot decrease item depth of root items var depth = getItemDepth(opts, state); if (depth == 1) { return transform; } var currentItem = getCurrentItem(opts, state); var currentList = document.getParent(currentItem.key); var parentItem = document.getParent(currentList.key); var parentList = document.getParent(parentItem.key); // The items following the item will be moved to a sublist of currentItem var followingItems = currentList.nodes.skipUntil(function (i) { return i === currentItem; }).rest(); // True if the currentItem and the followingItems make the whole // currentList, and hence the currentList will be emptied var willEmptyCurrentList = currentList.nodes.count() === followingItems.count() + 1; if (!followingItems.isEmpty()) { (function () { // Add them as sublist of currentItem var sublist = Slate.Block.create({ kind: 'block', type: currentList.type, data: currentList.data }); // Add the sublist transform = transform.insertNodeByKey(currentItem.key, currentItem.nodes.size, sublist, { normalize: false }); // Move the followingItems to the sublist transform = followingItems.reduce(function (tr, item) { return tr.moveNodeByKey(item.key, sublist.key, sublist.nodes.size, { normalize: false }); }, transform); })(); } // Move the item after parent item and normalize transform = transform.moveNodeByKey(currentItem.key, parentList.key, parentList.nodes.indexOf(parentItem) + 1); // Remove the currentList completely if needed if (willEmptyCurrentList) { transform = transform.removeNodeByKey(currentList.key); } return transform; } module.exports = decreaseItemDepth; },{"../getCurrentItem":3,"../getItemDepth":5,"slate":354}],18:[function(require,module,exports){ 'use strict'; var Slate = require('slate'); var getPreviousItem = require('../getPreviousItem'); var getCurrentItem = require('../getCurrentItem'); var getListForItem = require('../getListForItem'); var isList = require('../isList'); /** * Increase the depth of the current item by putting it in a sub-list * of previous item. * For first items in a list, does nothing. * * @param {PluginOptions} opts * @param {Slate.Transform} transform * @return {Transform} transform */ function increaseItemDepth(opts, transform) { var previousItem = getPreviousItem(opts, transform.state); if (!previousItem) { return transform; } var currentItem = getCurrentItem(opts, transform.state); // Move the item in the sublist of previous item return moveAsSubItem(opts, transform, currentItem, previousItem.key); } /** * Move the given item to the list at the end of destination node, * creating one if needed. * * @param {PluginOptions} opts * @param {Slate.Transform} transform * @param {Slate.Block} item The list item to add * @param {String} destKey The key of the destination node * @return {Slate.Transform} */ function moveAsSubItem(opts, transform, item, destKey) { var destination = transform.state.document.getDescendant(destKey); var lastIndex = destination.nodes.count(); var lastChild = destination.nodes.last(); // The potential existing last child list var existingList = isList(opts, lastChild) ? lastChild : null; if (existingList) { return transform.moveNodeByKey(item.key, existingList.key, existingList.nodes.count() // as last item ); } else { var currentList = getListForItem(opts, transform.state, destination); var newSublist = Slate.Block.create({ kind: 'block', type: currentList.type, data: currentList.data }); transform = transform.insertNodeByKey(destKey, lastIndex, newSublist); return transform.moveNodeByKey(item.key, newSublist.key, 0); } } module.exports = increaseItemDepth; },{"../getCurrentItem":3,"../getListForItem":7,"../getPreviousItem":8,"../isList":10,"slate":354}],19:[function(require,module,exports){ 'use strict'; var getCurrentItem = require('../getCurrentItem'); /** * Split a list item. * * @param {Object} opts * @param {Transform} transform * @return {Transform} transform */ function splitListItem(opts, transform) { var state = transform.state; var currentItem = getCurrentItem(opts, state); var splitOffset = currentItem.getOffsetAtRange(state.selection.collapseToStart()); return transform.splitNodeByKey(currentItem.key, splitOffset); } module.exports = splitListItem; },{"../getCurrentItem":3}],20:[function(require,module,exports){ 'use strict'; var getItemsAtRange = require('../getItemsAtRange'); /** * Unwrap items at range from their list. * * @param {PluginOptions} opts * @param {Slate.Transform} transform * @return {Transform} transform */ function unwrapList(opts, transform) { var items = getItemsAtRange(opts, transform.state); if (items.isEmpty()) { return transform; } // Unwrap the items from their list items.forEach(function (item) { return transform.unwrapNodeByKey(item.key); }); // Parent of the list of the items var firstItem = items.first(); var parent = transform.state.document.getParent(firstItem.key); var index = parent.nodes.findIndex(function (node) { return node.key === firstItem.key; }); // Unwrap the items' children items.forEach(function (item) { item.nodes.forEach(function (node) { transform.moveNodeByKey(node.key, parent.key, index, node, { normalize: false }); index++; }); }); // Finally, remove the now empty items items.forEach(function (item) { return transform.removeNodeByKey(item.key); }); return transform; } module.exports = unwrapList; },{"../getItemsAtRange":6}],21:[function(require,module,exports){ 'use strict'; var Slate = require('slate'); var _require = require('immutable'), List = _require.List; var isList = require('../isList'); /** * Wrap the blocks in the current selection in a new list. Selected * lists are merged together. * * @param {PluginOptions} opts * @param {Slate.Transform} transform * @param {Boolean} [ordered=false] * @param {Object|Data} [data] * @return {Transform} transform */ function wrapInList(opts, transform, ordered, data) { var selectedBlocks = getHighestSelectedBlocks(transform.state); // Wrap in container transform.wrapBlock({ type: ordered ? opts.typeOL : opts.typeUL, data: Slate.Data.create(data) }); // Wrap in list items selectedBlocks.forEach(function (node) { if (isList(opts, node)) { // Merge its items with the created list node.nodes.forEach(function (_ref) { var key = _ref.key; return transform.unwrapNodeByKey(key); }); } else { transform.wrapBlockByKey(node.key, opts.typeItem); } }); return transform; } /** * @param {Slate.State} state * @return {List<Block>} The highest list of blocks that cover the * current selection */ function getHighestSelectedBlocks(state) { var range = state.selection; var document = state.document; var startBlock = document.getClosestBlock(range.startKey); var endBlock = document.getClosestBlock(range.endKey); if (startBlock === endBlock) { return List([startBlock]); } else { var ancestor = document.getCommonAncestor(startBlock.key, endBlock.key); var startPath = ancestor.getPath(startBlock.key); var endPath = ancestor.getPath(endBlock.key); return ancestor.nodes.slice(startPath[0], endPath[0] + 1); } } module.exports = wrapInList; },{"../isList":10,"immutable":162,"slate":354}],22:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength exports.toByteArray = toByteArray exports.fromByteArray = fromByteArray var lookup = [] var revLookup = [] var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' for (var i = 0, len = code.length; i < len; ++i) { lookup[i] = code[i] revLookup[code.charCodeAt(i)] = i } revLookup['-'.charCodeAt(0)] = 62 revLookup['_'.charCodeAt(0)] = 63 function placeHoldersCount (b64) { var len = b64.length if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 } function byteLength (b64) { // base64 is 4/3 + up to two characters of the original data return b64.length * 3 / 4 - placeHoldersCount(b64) } function toByteArray (b64) { var i, j, l, tmp, placeHolders, arr var len = b64.length placeHolders = placeHoldersCount(b64) arr = new Arr(len * 3 / 4 - placeHolders) // if there are placeholders, only get up to the last complete 4 chars l = placeHolders > 0 ? len - 4 : len var L = 0 for (i = 0, j = 0; i < l; i += 4, j += 3) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] arr[L++] = (tmp >> 16) & 0xFF arr[L++] = (tmp >> 8) & 0xFF arr[L++] = tmp & 0xFF } if (placeHolders === 2) { tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) arr[L++] = tmp & 0xFF } else if (placeHolders === 1) { tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) arr[L++] = (tmp >> 8) & 0xFF arr[L++] = tmp & 0xFF } return arr } function tripletToBase64 (num) { return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] } function encodeChunk (uint8, start, end) { var tmp var output = [] for (var i = start; i < end; i += 3) { tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) output.push(tripletToBase64(tmp)) } return output.join('') } function fromByteArray (uint8) { var tmp var len = uint8.length var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes var output = '' var parts = [] var maxChunkLength = 16383 // must be multiple of 3 // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) } // pad the end with zeros, but make sure to not forget the extra bytes if (extraBytes === 1) { tmp = uint8[len - 1] output += lookup[tmp >> 2] output += lookup[(tmp << 4) & 0x3F] output += '==' } else if (extraBytes === 2) { tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) output += lookup[tmp >> 10] output += lookup[(tmp >> 4) & 0x3F] output += lookup[(tmp << 2) & 0x3F] output += '=' } parts.push(output) return parts.join('') } },{}],23:[function(require,module,exports){ module.exports = { trueFunc: function trueFunc(){ return true; }, falseFunc: function falseFunc(){ return false; } }; },{}],24:[function(require,module,exports){ },{}],25:[function(require,module,exports){ arguments[4][24][0].apply(exports,arguments) },{"dup":24}],26:[function(require,module,exports){ (function (global){ 'use strict'; var buffer = require('buffer'); var Buffer = buffer.Buffer; var SlowBuffer = buffer.SlowBuffer; var MAX_LEN = buffer.kMaxLength || 2147483647; exports.alloc = function alloc(size, fill, encoding) { if (typeof Buffer.alloc === 'function') { return Buffer.alloc(size, fill, encoding); } if (typeof encoding === 'number') { throw new TypeError('encoding must not be number'); } if (typeof size !== 'number') { throw new TypeError('size must be a number'); } if (size > MAX_LEN) { throw new RangeError('size is too large'); } var enc = encoding; var _fill = fill; if (_fill === undefined) { enc = undefined; _fill = 0; } var buf = new Buffer(size); if (typeof _fill === 'string') { var fillBuf = new Buffer(_fill, enc); var flen = fillBuf.length; var i = -1; while (++i < size) { buf[i] = fillBuf[i % flen]; } } else { buf.fill(_fill); } return buf; } exports.allocUnsafe = function allocUnsafe(size) { if (typeof Buffer.allocUnsafe === 'function') { return Buffer.allocUnsafe(size); } if (typeof size !== 'number') { throw new TypeError('size must be a number'); } if (size > MAX_LEN) { throw new RangeError('size is too large'); } return new Buffer(size); } exports.from = function from(value, encodingOrOffset, length) { if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) { return Buffer.from(value, encodingOrOffset, length); } if (typeof value === 'number') { throw new TypeError('"value" argument must not be a number'); } if (typeof value === 'string') { return new Buffer(value, encodingOrOffset); } if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { var offset = encodingOrOffset; if (arguments.length === 1) { return new Buffer(value); } if (typeof offset === 'undefined') { offset = 0; } var len = length; if (typeof len === 'undefined') { len = value.byteLength - offset; } if (offset >= value.byteLength) { throw new RangeError('\'offset\' is out of bounds'); } if (len > value.byteLength - offset) { throw new RangeError('\'length\' is out of bounds'); } return new Buffer(value.slice(offset, offset + len)); } if (Buffer.isBuffer(value)) { var out = new Buffer(value.length); value.copy(out, 0, 0, value.length); return out; } if (value) { if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) { return new Buffer(value); } if (value.type === 'Buffer' && Array.isArray(value.data)) { return new Buffer(value.data); } } throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.'); } exports.allocUnsafeSlow = function allocUnsafeSlow(size) { if (typeof Buffer.allocUnsafeSlow === 'function') { return Buffer.allocUnsafeSlow(size); } if (typeof size !== 'number') { throw new TypeError('size must be a number'); } if (size >= MAX_LEN) { throw new RangeError('size is too large'); } return new SlowBuffer(size); } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"buffer":27}],27:[function(require,module,exports){ (function (global){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> * @license MIT */ /* eslint-disable no-proto */ 'use strict' var base64 = require('base64-js') var ieee754 = require('ieee754') var isArray = require('isarray') exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Due to various browser bugs, sometimes the Object implementation will be used even * when the browser supports typed arrays. * * Note: * * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they * get the Object implementation, which is slower but behaves correctly. */ Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT : typedArraySupport() /* * Export kMaxLength after typed array support is determined. */ exports.kMaxLength = kMaxLength() function typedArraySupport () { try { var arr = new Uint8Array(1) arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} return arr.foo() === 42 && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } } function kMaxLength () { return Buffer.TYPED_ARRAY_SUPPORT ? 0x7fffffff : 0x3fffffff } function createBuffer (that, length) { if (kMaxLength() < length) { throw new RangeError('Invalid typed array length') } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = new Uint8Array(length) that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class if (that === null) { that = new Buffer(length) } that.length = length } return that } /** * The Buffer constructor returns instances of `Uint8Array` that have their * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of * `Uint8Array`, so the returned instances will have all the node `Buffer` methods * and the `Uint8Array` methods. Square bracket notation works as expected -- it * returns a single octet. * * The `Uint8Array` prototype remains unmodified. */ function Buffer (arg, encodingOrOffset, length) { if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { return new Buffer(arg, encodingOrOffset, length) } // Common case. if (typeof arg === 'number') { if (typeof encodingOrOffset === 'string') { throw new Error( 'If encoding is specified then the first argument must be a string' ) } return allocUnsafe(this, arg) } return from(this, arg, encodingOrOffset, length) } Buffer.poolSize = 8192 // not used by this implementation // TODO: Legacy, not needed anymore. Remove in next major version. Buffer._augment = function (arr) { arr.__proto__ = Buffer.prototype return arr } function from (that, value, encodingOrOffset, length) { if (typeof value === 'number') { throw new TypeError('"value" argument must not be a number') } if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { return fromArrayBuffer(that, value, encodingOrOffset, length) } if (typeof value === 'string') { return fromString(that, value, encodingOrOffset) } return fromObject(that, value) } /** * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError * if value is a number. * Buffer.from(str[, encoding]) * Buffer.from(array) * Buffer.from(buffer) * Buffer.from(arrayBuffer[, byteOffset[, length]]) **/ Buffer.from = function (value, encodingOrOffset, length) { return from(null, value, encodingOrOffset, length) } if (Buffer.TYPED_ARRAY_SUPPORT) { Buffer.prototype.__proto__ = Uint8Array.prototype Buffer.__proto__ = Uint8Array if (typeof Symbol !== 'undefined' && Symbol.species && Buffer[Symbol.species] === Buffer) { // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 Object.defineProperty(Buffer, Symbol.species, { value: null, configurable: true }) } } function assertSize (size) { if (typeof size !== 'number') { throw new TypeError('"size" argument must be a number') } else if (size < 0) { throw new RangeError('"size" argument must not be negative') } } function alloc (that, size, fill, encoding) { assertSize(size) if (size <= 0) { return createBuffer(that, size) } if (fill !== undefined) { // Only pay attention to encoding if it's a string. This // prevents accidentally sending in a number that would // be interpretted as a start offset. return typeof encoding === 'string' ? createBuffer(that, size).fill(fill, encoding) : createBuffer(that, size).fill(fill) } return createBuffer(that, size) } /** * Creates a new filled Buffer instance. * alloc(size[, fill[, encoding]]) **/ Buffer.alloc = function (size, fill, encoding) { return alloc(null, size, fill, encoding) } function allocUnsafe (that, size) { assertSize(size) that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < size; ++i) { that[i] = 0 } } return that } /** * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. * */ Buffer.allocUnsafe = function (size) { return allocUnsafe(null, size) } /** * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. */ Buffer.allocUnsafeSlow = function (size) { return allocUnsafe(null, size) } function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') { encoding = 'utf8' } if (!Buffer.isEncoding(encoding)) { throw new TypeError('"encoding" must be a valid string encoding') } var length = byteLength(string, encoding) | 0 that = createBuffer(that, length) var actual = that.write(string, encoding) if (actual !== length) { // Writing a hex string, for example, that contains invalid characters will // cause everything after the first invalid character to be ignored. (e.g. // 'abxxcd' will be treated as 'ab') that = that.slice(0, actual) } return that } function fromArrayLike (that, array) { var length = array.length < 0 ? 0 : checked(array.length) | 0 that = createBuffer(that, length) for (var i = 0; i < lengt