UNPKG

slate-edit-code

Version:

A Slate plugin to handle code blocks editing.

1,772 lines (1,437 loc) 1.67 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 PluginEditCode = require('../lib/'); var stateJson = require('./state'); var plugin = PluginEditCode(); var plugins = [plugin]; var SCHEMA = { nodes: { code_block: function code_block(props) { return React.createElement( 'div', _extends({ className: 'code' }, props.attributes), props.children ); }, code_line: function code_line(props) { return React.createElement( 'pre', props.attributes, props.children ); }, 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.State.fromJSON(stateJson) }; }, onChange: function onChange(_ref) { var state = _ref.state; this.setState({ state: state }); }, onToggleCode: function onToggleCode() { var state = this.state.state; this.onChange(plugin.changes.toggleCodeBlock(state.change(), 'paragraph').focus()); }, render: function render() { var state = this.state.state; return React.createElement( 'div', null, React.createElement( 'button', { onClick: this.onToggleCode }, plugin.utils.isInCodeBlock(state) ? 'Paragraph' : 'Code Block' ), React.createElement(Slate.Editor, { placeholder: 'Enter some text...', plugins: plugins, state: state, onChange: this.onChange, schema: SCHEMA }) ); } }); ReactDOM.render(React.createElement(Example, null), document.getElementById('example')); },{"../lib/":14,"./state":2,"react":309,"react-dom":153,"slate":330}],2:[function(require,module,exports){ module.exports={ "document": { "nodes": [ { "kind": "block", "type": "heading", "nodes": [ { "kind": "text", "ranges": [ { "text": "Slate + Code Edition" } ] } ] }, { "kind": "block", "type": "paragraph", "nodes": [ { "kind": "text", "ranges": [ { "text": "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." } ] } ] }, { "kind": "block", "type": "code_block", "nodes": [ { "kind": "block", "type": "code_line", "nodes": [ { "kind": "text", "ranges": [ { "text": "// Some JavaScript" } ] } ] }, { "kind": "block", "type": "code_line", "nodes": [ { "kind": "text", "ranges": [ { "text": "function hello() {" } ] } ] }, { "kind": "block", "type": "code_line", "nodes": [ { "kind": "text", "ranges": [ { "text": " console.log('Hello World')" } ] } ] }, { "kind": "block", "type": "code_line", "nodes": [ { "kind": "text", "ranges": [ { "text": "}" } ] } ] } ] }, { "kind": "block", "type": "paragraph", "nodes": [ { "kind": "text", "ranges": [ { "text": "End paragraph" } ] } ] } ] } } },{}],3:[function(require,module,exports){ "use strict"; /** * Dedent all lines in selection * @param {Change} change * @param {String} indent To remove * @return {Change} */ function dedentLines(opts, change, indent) { var state = change.state; var document = state.document, selection = state.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); } module.exports = dedentLines; },{}],4:[function(require,module,exports){ "use strict"; /** * Indent all lines in selection * @param {Change} change * @param {String} indent * @return {Change} */ function indentLines(opts, change, indent) { var state = change.state; var document = state.document, selection = state.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); } module.exports = indentLines; },{}],5:[function(require,module,exports){ 'use strict'; var wrapCodeBlock = require('./wrapCodeBlock'); var unwrapCodeBlock = require('./unwrapCodeBlock'); var isInCodeBlock = require('../isInCodeBlock'); /** * Toggle code block / paragraph. * @param {Change} change * @param {String} type * @return {Change} */ function toggleCodeBlock(opts, change, type) { if (isInCodeBlock(opts, change.state)) { return unwrapCodeBlock(opts, change, type); } else { return wrapCodeBlock(opts, change); } } module.exports = toggleCodeBlock; },{"../isInCodeBlock":15,"./unwrapCodeBlock":6,"./wrapCodeBlock":8}],6:[function(require,module,exports){ 'use strict'; var getCurrentCode = require('../getCurrentCode'); var unwrapCodeBlockByKey = require('./unwrapCodeBlockByKey'); /** * Convert a code block to a normal block. * @param {Change} change * @param {String} type * @return {Change} */ function unwrapCodeBlock(opts, change, type) { var _change = change, state = _change.state; var codeBlock = getCurrentCode(opts, state); if (!codeBlock) { return change; } // Convert to paragraph change = unwrapCodeBlockByKey(opts, change, codeBlock.key, type); return change; } module.exports = unwrapCodeBlock; },{"../getCurrentCode":11,"./unwrapCodeBlockByKey":7}],7:[function(require,module,exports){ 'use strict'; /** * Unwrap a code block into a normal block. * * @param {Change} change * @param {String} key * @param {String} type * @return {Change} */ function unwrapCodeBlockByKey(opts, change, key, type) { var state = change.state; var document = state.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 }).unwrapNodeByKey(line.key); }); return change; } module.exports = unwrapCodeBlockByKey; },{}],8:[function(require,module,exports){ 'use strict'; var wrapCodeBlockByKey = require('./wrapCodeBlockByKey'); /** * Wrap current block into a code block. * @param {Change} change * @return {Change} */ function wrapCodeBlock(opts, change) { var _change = change, state = _change.state; var startBlock = state.startBlock, selection = state.selection; // Convert to code block change = wrapCodeBlockByKey(opts, change, startBlock.key); // Move selection back in the block change.collapseToStartOf(change.state.document.getDescendant(startBlock.key)).moveOffsetsTo(selection.startOffset); return change; } module.exports = wrapCodeBlock; },{"./wrapCodeBlockByKey":9}],9:[function(require,module,exports){ 'use strict'; var deserializeCode = require('../deserializeCode'); /** * Wrap a block into a code block. * * @param {Change} change * @param {String} key * @return {Change} */ function wrapCodeBlockByKey(opts, change, key) { var state = change.state; var document = state.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 = deserializeCode(opts, text); toInsert.nodes.forEach(function (node, i) { change.insertNodeByKey(startBlock.key, i, node); }); // Set node type change.setNodeByKey(startBlock.key, { type: opts.containerType }); return change; } module.exports = wrapCodeBlockByKey; },{"../deserializeCode":10}],10:[function(require,module,exports){ 'use strict'; var _require = require('slate'), Block = _require.Block, Text = _require.Text; var _require2 = require('immutable'), List = _require2.List; var detectNewline = require('detect-newline'); var DEFAULT_NEWLINE = '\n'; /** * Deserialize a text into a code block * @param {Option} opts * @param {String} text * @return {Block} */ function deserializeCode(opts, text) { var sep = detectNewline(text) || DEFAULT_NEWLINE; var lines = List(text.split(sep)).map(function (line) { return Block.create({ type: opts.lineType, nodes: [Text.create(line)] }); }); var code = Block.create({ type: opts.containerType, nodes: lines }); return code; } module.exports = deserializeCode; },{"detect-newline":25,"immutable":135,"slate":330}],11:[function(require,module,exports){ "use strict"; /** * Return the current code block, from current selection or from a node key. * * @param {PluginOptions} opts * @param {Slate.State} state * @param {String} key? * @return {Slate.Block || Void} */ function getCurrentCode(opts, state, key) { var document = state.document; var currentBlock = void 0; if (key) { currentBlock = state.document.getDescendant(key); } else { if (!state.selection.startKey) return null; currentBlock = state.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; } else { return null; } } module.exports = getCurrentCode; },{}],12:[function(require,module,exports){ 'use strict'; var getIndent = require('./getIndent'); var getCurrentCode = require('./getCurrentCode'); /** * Detect indentation in the current code block * @param {Options} opts * @param {State} state * @return {String} */ function getCurrentIndent(opts, state) { var currentCode = getCurrentCode(opts, state); var text = currentCode.getTexts().map(function (t) { return t.text; }).join('\n'); return getIndent(text); } module.exports = getCurrentIndent; },{"./getCurrentCode":11,"./getIndent":13}],13:[function(require,module,exports){ 'use strict'; var detectIndent = require('detect-indent'); var DEFAULT_INDENTATION = ' '; /** * Detect indentation in a text * @param {String} text * @param {String} defaultValue? * @return {String} */ function getIndent(text) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_INDENTATION; return detectIndent(text).indent || defaultValue; } module.exports = getIndent; },{"detect-indent":24}],14:[function(require,module,exports){ 'use strict'; var _require = require('slate'), Document = _require.Document; var onEnter = require('./onEnter'); var onModEnter = require('./onModEnter'); var onTab = require('./onTab'); var onShiftTab = require('./onShiftTab'); var onBackspace = require('./onBackspace'); var onSelectAll = require('./onSelectAll'); var makeSchema = require('./makeSchema'); var getCurrentCode = require('./getCurrentCode'); var Options = require('./options'); var deserializeCode = require('./deserializeCode'); var isInCodeBlock = require('./isInCodeBlock'); var wrapCodeBlockByKey = require('./changes/wrapCodeBlockByKey'); var unwrapCodeBlockByKey = require('./changes/unwrapCodeBlockByKey'); var wrapCodeBlock = require('./changes/wrapCodeBlock'); var unwrapCodeBlock = require('./changes/unwrapCodeBlock'); var toggleCodeBlock = require('./changes/toggleCodeBlock'); var KEY_ENTER = 'enter'; var KEY_TAB = 'tab'; var KEY_BACKSPACE = 'backspace'; /** * A Slate plugin to handle keyboard events in code blocks. * @param {Options | Object} opts * @return {Object} */ function EditCode(opts) { opts = new Options(opts); /** * User is pressing a key in the editor */ function _onKeyDown(e, data, change) { var state = change.state; var currentCode = getCurrentCode(opts, state); // Inside code ? if (!currentCode) { return; } // Add opts in the argument list var args = [e, data, change, opts]; // Select all the code in the block (Mod+a) if (data.key === 'a' && data.isMod && opts.selectAll) { return onSelectAll.apply(undefined, args); } // User is pressing Shift+Tab else if (data.key === KEY_TAB && data.isShift) { return onShiftTab.apply(undefined, args); } // User is pressing Tab else if (data.key == KEY_TAB) { return onTab.apply(undefined, args); } // User is pressing Shift+Enter else if (data.key == KEY_ENTER && data.isMod && opts.exitBlockType) { return onModEnter.apply(undefined, args); } // User is pressing Enter else if (data.key == KEY_ENTER) { return onEnter.apply(undefined, args); } // User is pressing Backspace else if (data.key == KEY_BACKSPACE) { return onBackspace.apply(undefined, args); } } /** * User is pasting content, insert it as text */ function onPaste(event, data, change) { var state = change.state; var currentCode = getCurrentCode(opts, state); // Only handle paste when selection is completely a code block var endBlock = state.endBlock; if (!currentCode || !currentCode.hasDescendant(endBlock.key)) { return; } // 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 = deserializeCode(opts, text).nodes; var fragment = Document.create({ nodes: lines }); return change.insertFragment(fragment); } var schema = makeSchema(opts); return { onKeyDown: _onKeyDown, onPaste: onPaste, schema: schema, changes: { unwrapCodeBlockByKey: unwrapCodeBlockByKey.bind(null, opts), wrapCodeBlockByKey: wrapCodeBlockByKey.bind(null, opts), wrapCodeBlock: wrapCodeBlock.bind(null, opts), unwrapCodeBlock: unwrapCodeBlock.bind(null, opts), toggleCodeBlock: toggleCodeBlock.bind(null, opts) }, utils: { isInCodeBlock: isInCodeBlock.bind(null, opts), deserializeCode: deserializeCode.bind(null, opts) } }; } module.exports = EditCode; },{"./changes/toggleCodeBlock":5,"./changes/unwrapCodeBlock":6,"./changes/unwrapCodeBlockByKey":7,"./changes/wrapCodeBlock":8,"./changes/wrapCodeBlockByKey":9,"./deserializeCode":10,"./getCurrentCode":11,"./isInCodeBlock":15,"./makeSchema":16,"./onBackspace":17,"./onEnter":18,"./onModEnter":19,"./onSelectAll":20,"./onShiftTab":21,"./onTab":22,"./options":23,"slate":330}],15:[function(require,module,exports){ "use strict"; /** * Test if current selection is in a code block. * @param {State} state * @return {Boolean} */ function isInCodeBlock(opts, state) { var document = state.document, startKey = state.startKey; var codeBlock = document.getClosest(startKey, function (block) { return block.type === opts.containerType; }); return Boolean(codeBlock); } module.exports = isInCodeBlock; },{}],16:[function(require,module,exports){ 'use strict'; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _require = require('immutable'), Set = _require.Set, List = _require.List; var Slate = require('slate'); /** * Create a schema for code blocks. * @param {Options} opts * @return {Object} A schema definition with normalization rules */ function makeSchema(opts) { return { rules: [noOrphanLine(opts), onlyLine(opts), onlyText(opts), noMarks(opts)] }; } /** * @return {Object} A rule that ensure code lines are always children * of a code block. */ function noOrphanLine(opts) { return { // Match all blocks that are not code blocks match: function match(node) { return (node.kind === 'block' || node.kind === 'document') && node.type !== opts.containerType; }, validate: function validate(node) { var codeLines = node.nodes.filter(function (n) { return n.type === opts.lineType; }); if (codeLines.isEmpty()) { // All good return null; } else { // Wrap the orphan lines return { toWrap: codeLines }; } }, /** * Wrap the given blocks in code containers * @param {List<Nodes>} value.toWrap */ normalize: function normalize(change, node, value) { return value.toWrap.reduce(function (c, n) { return c.wrapBlockByKey(n.key, opts.containerType); }, change); } }; } /** * @return {Object} A rule that ensure code blocks only contain lines of code, and no marks */ function onlyLine(opts) { return { match: function match(node) { return node.type === opts.containerType; }, validate: function validate(node) { var nodes = node.nodes; var toWrap = []; var toRemove = []; nodes.forEach(function (child) { if (child.kind === 'text') toWrap.push(child);else if (child.type !== opts.lineType) toRemove.push(child); }); if (toWrap.length || toRemove.length) { return { toWrap: toWrap, toRemove: toRemove }; } else { return null; } }, normalize: function normalize(change, node, _ref) { var toWrap = _ref.toWrap, toRemove = _ref.toRemove; toRemove.forEach(function (child) { change.removeNodeByKey(child.key); }); toWrap.forEach(function (child) { change.wrapBlockByKey(child.key, opts.lineType); }); // Also remove marks here (since the no mark rule for // lines will not be applied afterward). return applyRule(noMarks(opts), change, node.key); } }; } /** * @return {Object} A rule that ensure code lines only contain one text * node. */ function onlyText(opts) { return { match: function match(node) { return node.type === opts.lineType; }, validate: function validate(node) { var nodes = node.nodes; var toRemove = nodes.filterNot(function (n) { return n.kind === 'text'; }); if (!toRemove.isEmpty()) { // Remove them, and the rest // will be done in the next validation call. return { toRemove: toRemove }; } // Else, there are only text nodes else if (nodes.size > 1) { return { toJoin: nodes }; } else if (nodes.size === 0) { return { toAdd: [Slate.Text.create()] }; } else { // There is a single text node -> valid return null; } }, /** * Clean up the child nodes. */ normalize: function normalize(change, node, _ref2) { var _ref2$toRemove = _ref2.toRemove, toRemove = _ref2$toRemove === undefined ? List() : _ref2$toRemove, _ref2$toAdd = _ref2.toAdd, toAdd = _ref2$toAdd === undefined ? List() : _ref2$toAdd, _ref2$toJoin = _ref2.toJoin, toJoin = _ref2$toJoin === undefined ? List() : _ref2$toJoin; // Remove invalids toRemove.reduce(function (c, child) { return c.removeNodeByKey(child.key, { normalize: false }); }, change); // Join nodes. var pairs = toJoin.butLast().map(function (child, index) { return [child.key, toJoin.get(index + 1).key]; }); // Join every node onto the previous one. pairs.reverse().reduce(function (c, _ref3) { var _ref4 = _slicedToArray(_ref3, 2), childKey = _ref4[0], nextChildKey = _ref4[1]; return c.joinNodeByKey(nextChildKey, childKey, { normalize: false }); }, change); // Add missing nodes toAdd.reduce(function (c, child) { return c.insertNodeByKey(node.key, 0, child); }, change); return change; } }; } /** * @return {Object} A rule that ensure code blocks contains no marks */ function noMarks(opts) { return { // Match at the line level, to optimize memoization match: function match(node) { return node.type === opts.lineType; }, validate: function validate(node) { if (opts.allowMarks) return null; var marks = getMarks(node); if (marks.isEmpty()) { return null; } else { return { removeMarks: marks }; } }, /** * Removes the given marks * @param {Set<Marks>} value.removeMarks */ normalize: function normalize(change, node, _ref5) { var removeMarks = _ref5.removeMarks; var selection = change.state.selection; var range = selection.moveToRangeOf(node); return removeMarks.reduce(function (c, mark) { return c.removeMarkAtRange(range, mark); }, change); } }; } /** * @param {Node} node * @return {Set<Marks>} All the marks in the node */ function getMarks(node) { var texts = node.getTexts(); var marks = texts.reduce(function (all, text) { return text.characters.reduce(function (accu, chars) { return accu.union(chars.marks); }, all); }, new Set()); return marks; } /** * Apply a normalization rule to a node * @param {Rule} rule * @param {Change} change * @param {String} key * @return {Change} */ function applyRule(rule, change, key) { var node = change.state.document.getDescendant(key); var notValid = rule.validate(node); if (notValid) { rule.normalize(change, node, notValid); } return change; } module.exports = makeSchema; },{"immutable":135,"slate":330}],17:[function(require,module,exports){ 'use strict'; var endsWith = require('ends-with'); var getCurrentIndent = require('./getCurrentIndent'); var getCurrentCode = require('./getCurrentCode'); /** * User pressed Delete in an editor: * Remove last idnentation before cursor */ function onBackspace(event, data, change, opts) { var state = change.state; if (state.isExpanded) { return; } var startOffset = state.startOffset, startText = state.startText; var currentLine = state.startBlock; // Detect and remove indentation at cursor var indent = getCurrentIndent(opts, state); var beforeSelection = currentLine.text.slice(0, startOffset); // If the line before selection ending with the indentation? if (endsWith(beforeSelection, indent)) { // Remove indent event.preventDefault(); return change.deleteBackward(indent.length).focus(); } // Otherwise check if we are in an empty code container... else if (opts.exitBlockType) { var currentCode = getCurrentCode(opts, state); 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.setBlock(opts.exitBlockType).unwrapNodeByKey(currentLine.key); } } } module.exports = onBackspace; },{"./getCurrentCode":11,"./getCurrentIndent":12,"ends-with":27}],18:[function(require,module,exports){ 'use strict'; var getIndent = require('./getIndent'); /** * User pressed Enter in an editor: * Insert a new code line and start it with the indentation from previous line */ function onEnter(event, data, change, opts) { var state = change.state; if (!state.isCollapsed) { return; } event.preventDefault(); var startBlock = state.startBlock; var currentLineText = startBlock.text; var indent = getIndent(currentLineText, ''); return change.splitBlock().insertText(indent).focus(); } module.exports = onEnter; },{"./getIndent":13}],19:[function(require,module,exports){ "use strict"; /** * User pressed Mod+Enter in an editor * Exit the current code block */ function onModEnter(event, data, change, opts) { var state = change.state; if (!state.isCollapsed) { return; } event.preventDefault(); // Exit the code block return opts.onExit(change, opts); } module.exports = onModEnter; },{}],20:[function(require,module,exports){ 'use strict'; var getCurrentCode = require('./getCurrentCode'); /** * User is Cmd+A to select all text */ function onSelectAll(event, data, change, opts) { var state = change.state; event.preventDefault(); var currentCode = getCurrentCode(opts, state); return change.collapseToStartOf(currentCode.getFirstText()).extendToEndOf(currentCode.getLastText()); } module.exports = onSelectAll; },{"./getCurrentCode":11}],21:[function(require,module,exports){ 'use strict'; var getCurrentIndent = require('./getCurrentIndent'); var dedentLines = require('./changes/dedentLines'); /** * User pressed Shift+Tab in an editor: * Reduce indentation in the selected lines. */ function onShiftTab(event, data, change, opts) { var state = change.state; event.preventDefault(); event.stopPropagation(); var indent = getCurrentIndent(opts, state); // We dedent all selected lines return dedentLines(opts, change, indent); } module.exports = onShiftTab; },{"./changes/dedentLines":3,"./getCurrentIndent":12}],22:[function(require,module,exports){ 'use strict'; var getCurrentIndent = require('./getCurrentIndent'); var indentLines = require('./changes/indentLines'); /** * User pressed Tab in an editor: * Insert a tab after detecting it from code block content. */ function onTab(event, data, change, opts) { var state = change.state; event.preventDefault(); event.stopPropagation(); var isCollapsed = state.isCollapsed; var indent = getCurrentIndent(opts, state); // Selection is collapsed, we just insert an indent at cursor if (isCollapsed) { return change.insertText(indent).focus(); } // We indent all selected lines return indentLines(opts, change, indent); } module.exports = onTab; },{"./changes/indentLines":4,"./getCurrentIndent":12}],23:[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 = { // Type of the code containers containerType: 'code_block', // Type of the code lines lineType: 'code_line', // Mod+Enter will exit the code container, into the given block type. // Backspace at start of empty code container, will turn it into the given block type. exitBlockType: 'paragraph', // Should the plugin handle the select all inside a code container selectAll: true, // Allow marks inside code blocks allowMarks: false, // Custom exit handler // exitBlockType option is useless if onExit is provided onExit: function onExit(change, options) { // Exit the code block change.insertBlock({ type: options.exitBlockType }); var inserted = change.state.startBlock; return change.unwrapNodeByKey(inserted.key); } }; /** * 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":135}],24:[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":310}],25:[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'; }; },{}],26:[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; },{}],27:[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; }; },{}],28:[function(require,module,exports){ 'use strict'; module.exports = require('./is-implemented')() ? Map : require('./polyfill'); },{"./is-implemented":29,"./polyfill":107}],29:[function(require,module,exports){ 'use strict'; module.exports = function () { var map, iterator, result; if (typeof Map !== 'function') return false; try { // WebKit doesn't support arguments and crashes map = new Map([['raz', 'one'], ['dwa', 'two'], ['trzy', 'three']]); } catch (e) { return false; } if (String(map) !== '[object Map]') return false; if (map.size !== 3) return false; if (typeof map.clear !== 'function') return false; if (typeof map.delete !== 'function') return false; if (typeof map.entries !== 'function') return false; if (typeof map.forEach !== 'function') return false; if (typeof map.get !== 'function') return false; if (typeof map.has !== 'function') return false; if (typeof map.keys !== 'function') return false; if (typeof map.set !== 'function') return false; if (typeof map.values !== 'function') return false; iterator = map.entries(); result = iterator.next(); if (result.done !== false) return false; if (!result.value) return false; if (result.value[0] !== 'raz') return false; if (result.value[1] !== 'one') return false; return true; }; },{}],30:[function(require,module,exports){ // Exports true if environment provides native `Map` implementation, // whatever that is. 'use strict'; module.exports = (function () { if (typeof Map === 'undefined') return false; return (Object.prototype.toString.call(new Map()) === '[object Map]'); }()); },{}],31:[function(require,module,exports){ 'use strict'; module.exports = require('es5-ext/object/primitive-set')('key', 'value', 'key+value'); },{"es5-ext/object/primitive-set":84}],32:[function(require,module,exports){ 'use strict'; var setPrototypeOf = require('es5-ext/object/set-prototype-of') , d = require('d') , Iterator = require('es6-iterator') , toStringTagSymbol = require('es6-symbol').toStringTag , kinds = require('./iterator-kinds') , defineProperties = Object.defineProperties , unBind = Iterator.prototype._unBind , MapIterator; MapIterator = module.exports = function (map, kind) { if (!(this instanceof MapIterator)) return new MapIterator(map, kind); Iterator.call(this, map.__mapKeysData__, map); if (!kind || !kinds[kind]) kind = 'key+value'; defineProperties(this, { __kind__: d('', kind), __values__: d('w', map.__mapValuesData__) }); }; if (setPrototypeOf) setPrototypeOf(MapIterator, Iterator); MapIterator.prototype = Object.create(Iterator.prototype, { constructor: d(MapIterator), _resolve: d(function (i) { if (this.__kind__ === 'value') return this.__values__[i]; if (this.__kind__ === 'key') return this.__list__[i]; return [this.__list__[i], this.__values__[i]]; }), _unBind: d(function () { this.__values__ = null; unBind.call(this); }), toString: d(function () { return '[object Map Iterator]'; }) }); Object.defineProperty(MapIterator.prototype, toStringTagSymbol, d('c', 'Map Iterator')); },{"./iterator-kinds":31,"d":34,"es5-ext/object/set-prototype-of":85,"es6-iterator":97,"es6-symbol":101}],33:[function(require,module,exports){ 'use strict'; var copy = require('es5-ext/object/copy') , normalizeOptions = require('es5-ext/object/normalize-options') , ensureCallable = require('es5-ext/object/valid-callable') , map = require('es5-ext/object/map') , callable = require('es5-ext/object/valid-callable') , validValue = require('es5-ext/object/valid-value') , bind = Function.prototype.bind, defineProperty = Object.defineProperty , hasOwnProperty = Object.prototype.hasOwnProperty , define; define = function (name, desc, options) { var value = validValue(desc) && callable(desc.value), dgs; dgs = copy(desc); delete dgs.writable; delete dgs.value; dgs.get = function () { if (!options.overwriteDefinition && hasOwnProperty.call(this, name)) return value; desc.value = bind.call(value, options.resolveContext ? options.resolveContext(this) : this); defineProperty(this, name, desc); return this[name]; }; return dgs; }; module.exports = function (props/*, options*/) { var options = normalizeOptions(arguments[1]); if (options.resolveContext != null) ensureCallable(options.resolveContext); return map(props, function (desc, name) { return define(name, desc, options); }); }; },{"es5-ext/object/copy":73,"es5-ext/object/map":82,"es5-ext/object/normalize-options":83,"es5-ext/object/valid-callable":88,"es5-ext/object/valid-value":89}],34:[function(require,module,exports){ 'use strict'; var assign = require('es5-ext/object/assign') , normalizeOpts = require('es5-ext/object/normalize-options') , isCallable = require('es5-ext/object/is-callable') , contains = require('es5-ext/string/#/contains') , d; d = module.exports = function (dscr, value/*, options*/) { var c, e, w, options, desc; if ((arguments.length < 2) || (typeof dscr !== 'string')) { options = value; value = dscr; dscr = null; } else { options = arguments[2]; } if (dscr == null) { c = w = true; e = false; } else { c = contains.call(dscr, 'c'); e = contains.call(dscr, 'e'); w = contains.call(dscr, 'w'); } desc = { value: value, configurable: c, enumerable: e, writable: w }; return !options ? desc : assign(normalizeOpts(options), desc); }; d.gs = function (dscr, get, set/*, options*/) { var c, e, options, desc; if (typeof dscr !== 'string') { options = set; set = get; get = dscr; dscr = null; } else { options = arguments[3]; } if (get == null) { get = undefined; } else if (!isCallable(get)) { options = get; get = set = undefined; } else if (set == null) { set = undefined; } else if (!isCallable(set)) { options = set; set = undefined; } if (dscr == null) { c = true; e = false; } else { c = contains.call(dscr, 'c'); e = contains.call(dscr, 'e'); } desc = { get: get, set: set, configurable: c, enumerable: e }; return !options ? desc : assign(normalizeOpts(options), desc); }; },{"es5-ext/object/assign":70,"es5-ext/object/is-callable":76,"es5-ext/object/normalize-options":83,"es5-ext/string/#/contains":90}],35:[function(require,module,exports){ // Inspired by Google Closure: // http://closure-library.googlecode.com/svn/docs/ // closure_goog_array_array.js.html#goog.array.clear "use strict"; var value = require("../../object/valid-value"); module.exports = function () { value(this).length = 0; return this; }; },{"../../object/valid-value":89}],36:[function(require,module,exports){ "use strict"; var numberIsNaN = require("../../number/is-nan") , toPosInt = require("../../number/to-pos-integer") , value = require("../../object/valid-value") , indexOf = Array.prototype.indexOf , objHasOwnProperty = Object.prototype.hasOwnProperty , abs = Math.abs , floor = Math.floor; module.exports = function (searchElement /*, fromIndex*/) { var i, length, fromIndex, val; if (!numberIsNaN(searchElement)) return indexOf.apply(this, arguments); length = toPosInt(value(this).length); fromIndex = arguments[1]; if (isNaN(fromIndex)) fromIndex = 0; else if (fromIndex >= 0) fromIndex = floor(fromIndex); else fromIndex = toPosInt(this.length) - floor(abs(fromIndex)); for (i = fromIndex; i < length; ++i) { if (objHasOwnProperty.call(this, i)) { val = this[i]; if (numberIsNaN(val)) return i; // Jslint: ignore } } return -1; }; },{"../../number/is-nan":64,"../../number/to-pos-integer":68,"../../object/valid-value":89}],37:[function(require,module,exports){ "use strict"; module.exports = require("./is-implemented")() ? Array.from : require("./shim"); },{"./is-implemented":38,"./shim":39}],38:[function(require,module,exports){ "use strict"; module.exports = function () { var from = Array.from, arr, result; if (typeof from !== "function") return false; arr = ["raz", "dwa"]; result = from(arr); return Boolean(result && (result !== arr) && (result[1] === "dwa")); }; },{}],39:[function(require,module,exports){ "use strict"; var iteratorSymbol = require("es6-symbol").iterator , isArguments = require("../../function/is-arguments") , isFunction = require("../../function/is-function") , toPosInt = require("../../number/to-pos-integer") , callable = require("../../object/valid-callable") , validValue = require("../../object/valid-value") , isValue = require("../../object/is-value") , isString = require("../../string/is-string") , isArray = Array.isArray , call = Function.prototype.call , desc = { configurable: true, enumerable: true, writable: true, value: null } , defineProperty = Object.defineProperty; // eslint-disable-next-line complexity module.exports = function (arrayLike /*, mapFn, thisArg*/) { var mapFn = arguments[1] , thisArg = arguments[2] , Context , i , j , arr , length , code , iterator , result , getIterator , value; arrayLike = Object(validValue(arrayLike)); if (isValue(mapFn)) callable(mapFn); if (!this || this === Array || !isFunction(this)) { // Result: Plain array if (!mapFn) { if (isArguments(arrayLike)) { // Source: Arguments length = arrayLike.length; if (length !== 1) return Array.apply(null, arrayLike); arr = new Array(1); arr[0] = arrayLike[0]; return arr; } if (isArray(arrayLike)) { // Source: Array arr = new Array(length = arrayLike.length); for (i = 0; i < length; ++i) arr[i] = arrayLike[i]; return arr; } } arr = []; } else { // Result: Non plain array Context = this; } if (!isArray(arrayLike)) { if ((getIterator = arrayLike[iteratorSymbol]) !== undefined) { // Source: Iterator iterator = callable(getIterator).call(arrayLike); if (Context) arr = new Context(); result = iterator.next(); i = 0; while (!result.done) { value = mapFn ? call.call(mapFn, thisArg, result.value, i) : result.value; if (Context) { desc.value = value; defineProperty(arr, i, desc); } else { arr[i] = value; } result = iterator.next(); ++i;