slate-edit-list
Version:
A Slate plugin to handle keyboard events in lists.
1,592 lines (1,318 loc) • 2.39 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 _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